blob: 96a7479052419d562fca8ebbf4e048ffbcae28ee [file] [log] [blame]
kesavand2cde6582020-06-22 04:56:23 -04001// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package http2
6
7import (
8 "bytes"
9 "encoding/binary"
10 "errors"
11 "fmt"
12 "io"
13 "log"
14 "strings"
15 "sync"
16
17 "golang.org/x/net/http/httpguts"
18 "golang.org/x/net/http2/hpack"
19)
20
21const frameHeaderLen = 9
22
23var padZeros = make([]byte, 255) // zeros for padding
24
25// A FrameType is a registered frame type as defined in
26// http://http2.github.io/http2-spec/#rfc.section.11.2
27type FrameType uint8
28
29const (
30 FrameData FrameType = 0x0
31 FrameHeaders FrameType = 0x1
32 FramePriority FrameType = 0x2
33 FrameRSTStream FrameType = 0x3
34 FrameSettings FrameType = 0x4
35 FramePushPromise FrameType = 0x5
36 FramePing FrameType = 0x6
37 FrameGoAway FrameType = 0x7
38 FrameWindowUpdate FrameType = 0x8
39 FrameContinuation FrameType = 0x9
40)
41
42var frameName = map[FrameType]string{
43 FrameData: "DATA",
44 FrameHeaders: "HEADERS",
45 FramePriority: "PRIORITY",
46 FrameRSTStream: "RST_STREAM",
47 FrameSettings: "SETTINGS",
48 FramePushPromise: "PUSH_PROMISE",
49 FramePing: "PING",
50 FrameGoAway: "GOAWAY",
51 FrameWindowUpdate: "WINDOW_UPDATE",
52 FrameContinuation: "CONTINUATION",
53}
54
55func (t FrameType) String() string {
56 if s, ok := frameName[t]; ok {
57 return s
58 }
59 return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
60}
61
62// Flags is a bitmask of HTTP/2 flags.
63// The meaning of flags varies depending on the frame type.
64type Flags uint8
65
66// Has reports whether f contains all (0 or more) flags in v.
67func (f Flags) Has(v Flags) bool {
68 return (f & v) == v
69}
70
71// Frame-specific FrameHeader flag bits.
72const (
73 // Data Frame
74 FlagDataEndStream Flags = 0x1
75 FlagDataPadded Flags = 0x8
76
77 // Headers Frame
78 FlagHeadersEndStream Flags = 0x1
79 FlagHeadersEndHeaders Flags = 0x4
80 FlagHeadersPadded Flags = 0x8
81 FlagHeadersPriority Flags = 0x20
82
83 // Settings Frame
84 FlagSettingsAck Flags = 0x1
85
86 // Ping Frame
87 FlagPingAck Flags = 0x1
88
89 // Continuation Frame
90 FlagContinuationEndHeaders Flags = 0x4
91
92 FlagPushPromiseEndHeaders Flags = 0x4
93 FlagPushPromisePadded Flags = 0x8
94)
95
96var flagName = map[FrameType]map[Flags]string{
97 FrameData: {
98 FlagDataEndStream: "END_STREAM",
99 FlagDataPadded: "PADDED",
100 },
101 FrameHeaders: {
102 FlagHeadersEndStream: "END_STREAM",
103 FlagHeadersEndHeaders: "END_HEADERS",
104 FlagHeadersPadded: "PADDED",
105 FlagHeadersPriority: "PRIORITY",
106 },
107 FrameSettings: {
108 FlagSettingsAck: "ACK",
109 },
110 FramePing: {
111 FlagPingAck: "ACK",
112 },
113 FrameContinuation: {
114 FlagContinuationEndHeaders: "END_HEADERS",
115 },
116 FramePushPromise: {
117 FlagPushPromiseEndHeaders: "END_HEADERS",
118 FlagPushPromisePadded: "PADDED",
119 },
120}
121
122// a frameParser parses a frame given its FrameHeader and payload
123// bytes. The length of payload will always equal fh.Length (which
124// might be 0).
kesavandc71914f2022-03-25 11:19:03 +0530125type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
kesavand2cde6582020-06-22 04:56:23 -0400126
127var frameParsers = map[FrameType]frameParser{
128 FrameData: parseDataFrame,
129 FrameHeaders: parseHeadersFrame,
130 FramePriority: parsePriorityFrame,
131 FrameRSTStream: parseRSTStreamFrame,
132 FrameSettings: parseSettingsFrame,
133 FramePushPromise: parsePushPromise,
134 FramePing: parsePingFrame,
135 FrameGoAway: parseGoAwayFrame,
136 FrameWindowUpdate: parseWindowUpdateFrame,
137 FrameContinuation: parseContinuationFrame,
138}
139
140func typeFrameParser(t FrameType) frameParser {
141 if f := frameParsers[t]; f != nil {
142 return f
143 }
144 return parseUnknownFrame
145}
146
147// A FrameHeader is the 9 byte header of all HTTP/2 frames.
148//
149// See http://http2.github.io/http2-spec/#FrameHeader
150type FrameHeader struct {
151 valid bool // caller can access []byte fields in the Frame
152
153 // Type is the 1 byte frame type. There are ten standard frame
154 // types, but extension frame types may be written by WriteRawFrame
155 // and will be returned by ReadFrame (as UnknownFrame).
156 Type FrameType
157
158 // Flags are the 1 byte of 8 potential bit flags per frame.
159 // They are specific to the frame type.
160 Flags Flags
161
162 // Length is the length of the frame, not including the 9 byte header.
163 // The maximum size is one byte less than 16MB (uint24), but only
164 // frames up to 16KB are allowed without peer agreement.
165 Length uint32
166
167 // StreamID is which stream this frame is for. Certain frames
168 // are not stream-specific, in which case this field is 0.
169 StreamID uint32
170}
171
172// Header returns h. It exists so FrameHeaders can be embedded in other
173// specific frame types and implement the Frame interface.
174func (h FrameHeader) Header() FrameHeader { return h }
175
176func (h FrameHeader) String() string {
177 var buf bytes.Buffer
178 buf.WriteString("[FrameHeader ")
179 h.writeDebug(&buf)
180 buf.WriteByte(']')
181 return buf.String()
182}
183
184func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
185 buf.WriteString(h.Type.String())
186 if h.Flags != 0 {
187 buf.WriteString(" flags=")
188 set := 0
189 for i := uint8(0); i < 8; i++ {
190 if h.Flags&(1<<i) == 0 {
191 continue
192 }
193 set++
194 if set > 1 {
195 buf.WriteByte('|')
196 }
197 name := flagName[h.Type][Flags(1<<i)]
198 if name != "" {
199 buf.WriteString(name)
200 } else {
201 fmt.Fprintf(buf, "0x%x", 1<<i)
202 }
203 }
204 }
205 if h.StreamID != 0 {
206 fmt.Fprintf(buf, " stream=%d", h.StreamID)
207 }
208 fmt.Fprintf(buf, " len=%d", h.Length)
209}
210
211func (h *FrameHeader) checkValid() {
212 if !h.valid {
213 panic("Frame accessor called on non-owned Frame")
214 }
215}
216
217func (h *FrameHeader) invalidate() { h.valid = false }
218
219// frame header bytes.
220// Used only by ReadFrameHeader.
221var fhBytes = sync.Pool{
222 New: func() interface{} {
223 buf := make([]byte, frameHeaderLen)
224 return &buf
225 },
226}
227
228// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
229// Most users should use Framer.ReadFrame instead.
230func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
231 bufp := fhBytes.Get().(*[]byte)
232 defer fhBytes.Put(bufp)
233 return readFrameHeader(*bufp, r)
234}
235
236func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
237 _, err := io.ReadFull(r, buf[:frameHeaderLen])
238 if err != nil {
239 return FrameHeader{}, err
240 }
241 return FrameHeader{
242 Length: (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
243 Type: FrameType(buf[3]),
244 Flags: Flags(buf[4]),
245 StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
246 valid: true,
247 }, nil
248}
249
250// A Frame is the base interface implemented by all frame types.
251// Callers will generally type-assert the specific frame type:
252// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
253//
254// Frames are only valid until the next call to Framer.ReadFrame.
255type Frame interface {
256 Header() FrameHeader
257
258 // invalidate is called by Framer.ReadFrame to make this
259 // frame's buffers as being invalid, since the subsequent
260 // frame will reuse them.
261 invalidate()
262}
263
264// A Framer reads and writes Frames.
265type Framer struct {
266 r io.Reader
267 lastFrame Frame
268 errDetail error
269
kesavandc71914f2022-03-25 11:19:03 +0530270 // countError is a non-nil func that's called on a frame parse
271 // error with some unique error path token. It's initialized
272 // from Transport.CountError or Server.CountError.
273 countError func(errToken string)
274
kesavand2cde6582020-06-22 04:56:23 -0400275 // lastHeaderStream is non-zero if the last frame was an
276 // unfinished HEADERS/CONTINUATION.
277 lastHeaderStream uint32
278
279 maxReadSize uint32
280 headerBuf [frameHeaderLen]byte
281
282 // TODO: let getReadBuf be configurable, and use a less memory-pinning
283 // allocator in server.go to minimize memory pinned for many idle conns.
284 // Will probably also need to make frame invalidation have a hook too.
285 getReadBuf func(size uint32) []byte
286 readBuf []byte // cache for default getReadBuf
287
288 maxWriteSize uint32 // zero means unlimited; TODO: implement
289
290 w io.Writer
291 wbuf []byte
292
293 // AllowIllegalWrites permits the Framer's Write methods to
294 // write frames that do not conform to the HTTP/2 spec. This
295 // permits using the Framer to test other HTTP/2
296 // implementations' conformance to the spec.
297 // If false, the Write methods will prefer to return an error
298 // rather than comply.
299 AllowIllegalWrites bool
300
301 // AllowIllegalReads permits the Framer's ReadFrame method
302 // to return non-compliant frames or frame orders.
303 // This is for testing and permits using the Framer to test
304 // other HTTP/2 implementations' conformance to the spec.
305 // It is not compatible with ReadMetaHeaders.
306 AllowIllegalReads bool
307
308 // ReadMetaHeaders if non-nil causes ReadFrame to merge
309 // HEADERS and CONTINUATION frames together and return
310 // MetaHeadersFrame instead.
311 ReadMetaHeaders *hpack.Decoder
312
313 // MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
314 // It's used only if ReadMetaHeaders is set; 0 means a sane default
315 // (currently 16MB)
316 // If the limit is hit, MetaHeadersFrame.Truncated is set true.
317 MaxHeaderListSize uint32
318
319 // TODO: track which type of frame & with which flags was sent
320 // last. Then return an error (unless AllowIllegalWrites) if
321 // we're in the middle of a header block and a
322 // non-Continuation or Continuation on a different stream is
323 // attempted to be written.
324
325 logReads, logWrites bool
326
327 debugFramer *Framer // only use for logging written writes
328 debugFramerBuf *bytes.Buffer
329 debugReadLoggerf func(string, ...interface{})
330 debugWriteLoggerf func(string, ...interface{})
331
332 frameCache *frameCache // nil if frames aren't reused (default)
333}
334
335func (fr *Framer) maxHeaderListSize() uint32 {
336 if fr.MaxHeaderListSize == 0 {
337 return 16 << 20 // sane default, per docs
338 }
339 return fr.MaxHeaderListSize
340}
341
342func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
343 // Write the FrameHeader.
344 f.wbuf = append(f.wbuf[:0],
345 0, // 3 bytes of length, filled in in endWrite
346 0,
347 0,
348 byte(ftype),
349 byte(flags),
350 byte(streamID>>24),
351 byte(streamID>>16),
352 byte(streamID>>8),
353 byte(streamID))
354}
355
356func (f *Framer) endWrite() error {
357 // Now that we know the final size, fill in the FrameHeader in
358 // the space previously reserved for it. Abuse append.
359 length := len(f.wbuf) - frameHeaderLen
360 if length >= (1 << 24) {
361 return ErrFrameTooLarge
362 }
363 _ = append(f.wbuf[:0],
364 byte(length>>16),
365 byte(length>>8),
366 byte(length))
367 if f.logWrites {
368 f.logWrite()
369 }
370
371 n, err := f.w.Write(f.wbuf)
372 if err == nil && n != len(f.wbuf) {
373 err = io.ErrShortWrite
374 }
375 return err
376}
377
378func (f *Framer) logWrite() {
379 if f.debugFramer == nil {
380 f.debugFramerBuf = new(bytes.Buffer)
381 f.debugFramer = NewFramer(nil, f.debugFramerBuf)
382 f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
383 // Let us read anything, even if we accidentally wrote it
384 // in the wrong order:
385 f.debugFramer.AllowIllegalReads = true
386 }
387 f.debugFramerBuf.Write(f.wbuf)
388 fr, err := f.debugFramer.ReadFrame()
389 if err != nil {
390 f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
391 return
392 }
393 f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
394}
395
396func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
397func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
398func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
399func (f *Framer) writeUint32(v uint32) {
400 f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
401}
402
403const (
404 minMaxFrameSize = 1 << 14
405 maxFrameSize = 1<<24 - 1
406)
407
408// SetReuseFrames allows the Framer to reuse Frames.
409// If called on a Framer, Frames returned by calls to ReadFrame are only
410// valid until the next call to ReadFrame.
411func (fr *Framer) SetReuseFrames() {
412 if fr.frameCache != nil {
413 return
414 }
415 fr.frameCache = &frameCache{}
416}
417
418type frameCache struct {
419 dataFrame DataFrame
420}
421
422func (fc *frameCache) getDataFrame() *DataFrame {
423 if fc == nil {
424 return &DataFrame{}
425 }
426 return &fc.dataFrame
427}
428
429// NewFramer returns a Framer that writes frames to w and reads them from r.
430func NewFramer(w io.Writer, r io.Reader) *Framer {
431 fr := &Framer{
432 w: w,
433 r: r,
kesavandc71914f2022-03-25 11:19:03 +0530434 countError: func(string) {},
kesavand2cde6582020-06-22 04:56:23 -0400435 logReads: logFrameReads,
436 logWrites: logFrameWrites,
437 debugReadLoggerf: log.Printf,
438 debugWriteLoggerf: log.Printf,
439 }
440 fr.getReadBuf = func(size uint32) []byte {
441 if cap(fr.readBuf) >= int(size) {
442 return fr.readBuf[:size]
443 }
444 fr.readBuf = make([]byte, size)
445 return fr.readBuf
446 }
447 fr.SetMaxReadFrameSize(maxFrameSize)
448 return fr
449}
450
451// SetMaxReadFrameSize sets the maximum size of a frame
452// that will be read by a subsequent call to ReadFrame.
453// It is the caller's responsibility to advertise this
454// limit with a SETTINGS frame.
455func (fr *Framer) SetMaxReadFrameSize(v uint32) {
456 if v > maxFrameSize {
457 v = maxFrameSize
458 }
459 fr.maxReadSize = v
460}
461
462// ErrorDetail returns a more detailed error of the last error
463// returned by Framer.ReadFrame. For instance, if ReadFrame
464// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
465// will say exactly what was invalid. ErrorDetail is not guaranteed
466// to return a non-nil value and like the rest of the http2 package,
467// its return value is not protected by an API compatibility promise.
468// ErrorDetail is reset after the next call to ReadFrame.
469func (fr *Framer) ErrorDetail() error {
470 return fr.errDetail
471}
472
473// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
474// sends a frame that is larger than declared with SetMaxReadFrameSize.
475var ErrFrameTooLarge = errors.New("http2: frame too large")
476
477// terminalReadFrameError reports whether err is an unrecoverable
478// error from ReadFrame and no other frames should be read.
479func terminalReadFrameError(err error) bool {
480 if _, ok := err.(StreamError); ok {
481 return false
482 }
483 return err != nil
484}
485
486// ReadFrame reads a single frame. The returned Frame is only valid
487// until the next call to ReadFrame.
488//
489// If the frame is larger than previously set with SetMaxReadFrameSize, the
490// returned error is ErrFrameTooLarge. Other errors may be of type
491// ConnectionError, StreamError, or anything else from the underlying
492// reader.
493func (fr *Framer) ReadFrame() (Frame, error) {
494 fr.errDetail = nil
495 if fr.lastFrame != nil {
496 fr.lastFrame.invalidate()
497 }
498 fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
499 if err != nil {
500 return nil, err
501 }
502 if fh.Length > fr.maxReadSize {
503 return nil, ErrFrameTooLarge
504 }
505 payload := fr.getReadBuf(fh.Length)
506 if _, err := io.ReadFull(fr.r, payload); err != nil {
507 return nil, err
508 }
kesavandc71914f2022-03-25 11:19:03 +0530509 f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload)
kesavand2cde6582020-06-22 04:56:23 -0400510 if err != nil {
511 if ce, ok := err.(connError); ok {
512 return nil, fr.connError(ce.Code, ce.Reason)
513 }
514 return nil, err
515 }
516 if err := fr.checkFrameOrder(f); err != nil {
517 return nil, err
518 }
519 if fr.logReads {
520 fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
521 }
522 if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil {
523 return fr.readMetaFrame(f.(*HeadersFrame))
524 }
525 return f, nil
526}
527
528// connError returns ConnectionError(code) but first
529// stashes away a public reason to the caller can optionally relay it
530// to the peer before hanging up on them. This might help others debug
531// their implementations.
532func (fr *Framer) connError(code ErrCode, reason string) error {
533 fr.errDetail = errors.New(reason)
534 return ConnectionError(code)
535}
536
537// checkFrameOrder reports an error if f is an invalid frame to return
538// next from ReadFrame. Mostly it checks whether HEADERS and
539// CONTINUATION frames are contiguous.
540func (fr *Framer) checkFrameOrder(f Frame) error {
541 last := fr.lastFrame
542 fr.lastFrame = f
543 if fr.AllowIllegalReads {
544 return nil
545 }
546
547 fh := f.Header()
548 if fr.lastHeaderStream != 0 {
549 if fh.Type != FrameContinuation {
550 return fr.connError(ErrCodeProtocol,
551 fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
552 fh.Type, fh.StreamID,
553 last.Header().Type, fr.lastHeaderStream))
554 }
555 if fh.StreamID != fr.lastHeaderStream {
556 return fr.connError(ErrCodeProtocol,
557 fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
558 fh.StreamID, fr.lastHeaderStream))
559 }
560 } else if fh.Type == FrameContinuation {
561 return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
562 }
563
564 switch fh.Type {
565 case FrameHeaders, FrameContinuation:
566 if fh.Flags.Has(FlagHeadersEndHeaders) {
567 fr.lastHeaderStream = 0
568 } else {
569 fr.lastHeaderStream = fh.StreamID
570 }
571 }
572
573 return nil
574}
575
576// A DataFrame conveys arbitrary, variable-length sequences of octets
577// associated with a stream.
578// See http://http2.github.io/http2-spec/#rfc.section.6.1
579type DataFrame struct {
580 FrameHeader
581 data []byte
582}
583
584func (f *DataFrame) StreamEnded() bool {
585 return f.FrameHeader.Flags.Has(FlagDataEndStream)
586}
587
588// Data returns the frame's data octets, not including any padding
589// size byte or padding suffix bytes.
590// The caller must not retain the returned memory past the next
591// call to ReadFrame.
592func (f *DataFrame) Data() []byte {
593 f.checkValid()
594 return f.data
595}
596
kesavandc71914f2022-03-25 11:19:03 +0530597func parseDataFrame(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400598 if fh.StreamID == 0 {
599 // DATA frames MUST be associated with a stream. If a
600 // DATA frame is received whose stream identifier
601 // field is 0x0, the recipient MUST respond with a
602 // connection error (Section 5.4.1) of type
603 // PROTOCOL_ERROR.
kesavandc71914f2022-03-25 11:19:03 +0530604 countError("frame_data_stream_0")
kesavand2cde6582020-06-22 04:56:23 -0400605 return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
606 }
607 f := fc.getDataFrame()
608 f.FrameHeader = fh
609
610 var padSize byte
611 if fh.Flags.Has(FlagDataPadded) {
612 var err error
613 payload, padSize, err = readByte(payload)
614 if err != nil {
kesavandc71914f2022-03-25 11:19:03 +0530615 countError("frame_data_pad_byte_short")
kesavand2cde6582020-06-22 04:56:23 -0400616 return nil, err
617 }
618 }
619 if int(padSize) > len(payload) {
620 // If the length of the padding is greater than the
621 // length of the frame payload, the recipient MUST
622 // treat this as a connection error.
623 // Filed: https://github.com/http2/http2-spec/issues/610
kesavandc71914f2022-03-25 11:19:03 +0530624 countError("frame_data_pad_too_big")
kesavand2cde6582020-06-22 04:56:23 -0400625 return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
626 }
627 f.data = payload[:len(payload)-int(padSize)]
628 return f, nil
629}
630
631var (
632 errStreamID = errors.New("invalid stream ID")
633 errDepStreamID = errors.New("invalid dependent stream ID")
634 errPadLength = errors.New("pad length too large")
635 errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
636)
637
638func validStreamIDOrZero(streamID uint32) bool {
639 return streamID&(1<<31) == 0
640}
641
642func validStreamID(streamID uint32) bool {
643 return streamID != 0 && streamID&(1<<31) == 0
644}
645
646// WriteData writes a DATA frame.
647//
648// It will perform exactly one Write to the underlying Writer.
649// It is the caller's responsibility not to violate the maximum frame size
650// and to not call other Write methods concurrently.
651func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
652 return f.WriteDataPadded(streamID, endStream, data, nil)
653}
654
655// WriteDataPadded writes a DATA frame with optional padding.
656//
657// If pad is nil, the padding bit is not sent.
658// The length of pad must not exceed 255 bytes.
659// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
660//
661// It will perform exactly one Write to the underlying Writer.
662// It is the caller's responsibility not to violate the maximum frame size
663// and to not call other Write methods concurrently.
664func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
665 if !validStreamID(streamID) && !f.AllowIllegalWrites {
666 return errStreamID
667 }
668 if len(pad) > 0 {
669 if len(pad) > 255 {
670 return errPadLength
671 }
672 if !f.AllowIllegalWrites {
673 for _, b := range pad {
674 if b != 0 {
675 // "Padding octets MUST be set to zero when sending."
676 return errPadBytes
677 }
678 }
679 }
680 }
681 var flags Flags
682 if endStream {
683 flags |= FlagDataEndStream
684 }
685 if pad != nil {
686 flags |= FlagDataPadded
687 }
688 f.startWrite(FrameData, flags, streamID)
689 if pad != nil {
690 f.wbuf = append(f.wbuf, byte(len(pad)))
691 }
692 f.wbuf = append(f.wbuf, data...)
693 f.wbuf = append(f.wbuf, pad...)
694 return f.endWrite()
695}
696
697// A SettingsFrame conveys configuration parameters that affect how
698// endpoints communicate, such as preferences and constraints on peer
699// behavior.
700//
701// See http://http2.github.io/http2-spec/#SETTINGS
702type SettingsFrame struct {
703 FrameHeader
704 p []byte
705}
706
kesavandc71914f2022-03-25 11:19:03 +0530707func parseSettingsFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400708 if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
709 // When this (ACK 0x1) bit is set, the payload of the
710 // SETTINGS frame MUST be empty. Receipt of a
711 // SETTINGS frame with the ACK flag set and a length
712 // field value other than 0 MUST be treated as a
713 // connection error (Section 5.4.1) of type
714 // FRAME_SIZE_ERROR.
kesavandc71914f2022-03-25 11:19:03 +0530715 countError("frame_settings_ack_with_length")
kesavand2cde6582020-06-22 04:56:23 -0400716 return nil, ConnectionError(ErrCodeFrameSize)
717 }
718 if fh.StreamID != 0 {
719 // SETTINGS frames always apply to a connection,
720 // never a single stream. The stream identifier for a
721 // SETTINGS frame MUST be zero (0x0). If an endpoint
722 // receives a SETTINGS frame whose stream identifier
723 // field is anything other than 0x0, the endpoint MUST
724 // respond with a connection error (Section 5.4.1) of
725 // type PROTOCOL_ERROR.
kesavandc71914f2022-03-25 11:19:03 +0530726 countError("frame_settings_has_stream")
kesavand2cde6582020-06-22 04:56:23 -0400727 return nil, ConnectionError(ErrCodeProtocol)
728 }
729 if len(p)%6 != 0 {
kesavandc71914f2022-03-25 11:19:03 +0530730 countError("frame_settings_mod_6")
kesavand2cde6582020-06-22 04:56:23 -0400731 // Expecting even number of 6 byte settings.
732 return nil, ConnectionError(ErrCodeFrameSize)
733 }
734 f := &SettingsFrame{FrameHeader: fh, p: p}
735 if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
kesavandc71914f2022-03-25 11:19:03 +0530736 countError("frame_settings_window_size_too_big")
kesavand2cde6582020-06-22 04:56:23 -0400737 // Values above the maximum flow control window size of 2^31 - 1 MUST
738 // be treated as a connection error (Section 5.4.1) of type
739 // FLOW_CONTROL_ERROR.
740 return nil, ConnectionError(ErrCodeFlowControl)
741 }
742 return f, nil
743}
744
745func (f *SettingsFrame) IsAck() bool {
746 return f.FrameHeader.Flags.Has(FlagSettingsAck)
747}
748
749func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
750 f.checkValid()
751 for i := 0; i < f.NumSettings(); i++ {
752 if s := f.Setting(i); s.ID == id {
753 return s.Val, true
754 }
755 }
756 return 0, false
757}
758
759// Setting returns the setting from the frame at the given 0-based index.
760// The index must be >= 0 and less than f.NumSettings().
761func (f *SettingsFrame) Setting(i int) Setting {
762 buf := f.p
763 return Setting{
764 ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
765 Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
766 }
767}
768
769func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
770
771// HasDuplicates reports whether f contains any duplicate setting IDs.
772func (f *SettingsFrame) HasDuplicates() bool {
773 num := f.NumSettings()
774 if num == 0 {
775 return false
776 }
777 // If it's small enough (the common case), just do the n^2
778 // thing and avoid a map allocation.
779 if num < 10 {
780 for i := 0; i < num; i++ {
781 idi := f.Setting(i).ID
782 for j := i + 1; j < num; j++ {
783 idj := f.Setting(j).ID
784 if idi == idj {
785 return true
786 }
787 }
788 }
789 return false
790 }
791 seen := map[SettingID]bool{}
792 for i := 0; i < num; i++ {
793 id := f.Setting(i).ID
794 if seen[id] {
795 return true
796 }
797 seen[id] = true
798 }
799 return false
800}
801
802// ForeachSetting runs fn for each setting.
803// It stops and returns the first error.
804func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
805 f.checkValid()
806 for i := 0; i < f.NumSettings(); i++ {
807 if err := fn(f.Setting(i)); err != nil {
808 return err
809 }
810 }
811 return nil
812}
813
814// WriteSettings writes a SETTINGS frame with zero or more settings
815// specified and the ACK bit not set.
816//
817// It will perform exactly one Write to the underlying Writer.
818// It is the caller's responsibility to not call other Write methods concurrently.
819func (f *Framer) WriteSettings(settings ...Setting) error {
820 f.startWrite(FrameSettings, 0, 0)
821 for _, s := range settings {
822 f.writeUint16(uint16(s.ID))
823 f.writeUint32(s.Val)
824 }
825 return f.endWrite()
826}
827
828// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
829//
830// It will perform exactly one Write to the underlying Writer.
831// It is the caller's responsibility to not call other Write methods concurrently.
832func (f *Framer) WriteSettingsAck() error {
833 f.startWrite(FrameSettings, FlagSettingsAck, 0)
834 return f.endWrite()
835}
836
837// A PingFrame is a mechanism for measuring a minimal round trip time
838// from the sender, as well as determining whether an idle connection
839// is still functional.
840// See http://http2.github.io/http2-spec/#rfc.section.6.7
841type PingFrame struct {
842 FrameHeader
843 Data [8]byte
844}
845
846func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
847
kesavandc71914f2022-03-25 11:19:03 +0530848func parsePingFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400849 if len(payload) != 8 {
kesavandc71914f2022-03-25 11:19:03 +0530850 countError("frame_ping_length")
kesavand2cde6582020-06-22 04:56:23 -0400851 return nil, ConnectionError(ErrCodeFrameSize)
852 }
853 if fh.StreamID != 0 {
kesavandc71914f2022-03-25 11:19:03 +0530854 countError("frame_ping_has_stream")
kesavand2cde6582020-06-22 04:56:23 -0400855 return nil, ConnectionError(ErrCodeProtocol)
856 }
857 f := &PingFrame{FrameHeader: fh}
858 copy(f.Data[:], payload)
859 return f, nil
860}
861
862func (f *Framer) WritePing(ack bool, data [8]byte) error {
863 var flags Flags
864 if ack {
865 flags = FlagPingAck
866 }
867 f.startWrite(FramePing, flags, 0)
868 f.writeBytes(data[:])
869 return f.endWrite()
870}
871
872// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
873// See http://http2.github.io/http2-spec/#rfc.section.6.8
874type GoAwayFrame struct {
875 FrameHeader
876 LastStreamID uint32
877 ErrCode ErrCode
878 debugData []byte
879}
880
881// DebugData returns any debug data in the GOAWAY frame. Its contents
882// are not defined.
883// The caller must not retain the returned memory past the next
884// call to ReadFrame.
885func (f *GoAwayFrame) DebugData() []byte {
886 f.checkValid()
887 return f.debugData
888}
889
kesavandc71914f2022-03-25 11:19:03 +0530890func parseGoAwayFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400891 if fh.StreamID != 0 {
kesavandc71914f2022-03-25 11:19:03 +0530892 countError("frame_goaway_has_stream")
kesavand2cde6582020-06-22 04:56:23 -0400893 return nil, ConnectionError(ErrCodeProtocol)
894 }
895 if len(p) < 8 {
kesavandc71914f2022-03-25 11:19:03 +0530896 countError("frame_goaway_short")
kesavand2cde6582020-06-22 04:56:23 -0400897 return nil, ConnectionError(ErrCodeFrameSize)
898 }
899 return &GoAwayFrame{
900 FrameHeader: fh,
901 LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
902 ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])),
903 debugData: p[8:],
904 }, nil
905}
906
907func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
908 f.startWrite(FrameGoAway, 0, 0)
909 f.writeUint32(maxStreamID & (1<<31 - 1))
910 f.writeUint32(uint32(code))
911 f.writeBytes(debugData)
912 return f.endWrite()
913}
914
915// An UnknownFrame is the frame type returned when the frame type is unknown
916// or no specific frame type parser exists.
917type UnknownFrame struct {
918 FrameHeader
919 p []byte
920}
921
922// Payload returns the frame's payload (after the header). It is not
923// valid to call this method after a subsequent call to
924// Framer.ReadFrame, nor is it valid to retain the returned slice.
925// The memory is owned by the Framer and is invalidated when the next
926// frame is read.
927func (f *UnknownFrame) Payload() []byte {
928 f.checkValid()
929 return f.p
930}
931
kesavandc71914f2022-03-25 11:19:03 +0530932func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400933 return &UnknownFrame{fh, p}, nil
934}
935
936// A WindowUpdateFrame is used to implement flow control.
937// See http://http2.github.io/http2-spec/#rfc.section.6.9
938type WindowUpdateFrame struct {
939 FrameHeader
940 Increment uint32 // never read with high bit set
941}
942
kesavandc71914f2022-03-25 11:19:03 +0530943func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -0400944 if len(p) != 4 {
kesavandc71914f2022-03-25 11:19:03 +0530945 countError("frame_windowupdate_bad_len")
kesavand2cde6582020-06-22 04:56:23 -0400946 return nil, ConnectionError(ErrCodeFrameSize)
947 }
948 inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
949 if inc == 0 {
950 // A receiver MUST treat the receipt of a
951 // WINDOW_UPDATE frame with an flow control window
952 // increment of 0 as a stream error (Section 5.4.2) of
953 // type PROTOCOL_ERROR; errors on the connection flow
954 // control window MUST be treated as a connection
955 // error (Section 5.4.1).
956 if fh.StreamID == 0 {
kesavandc71914f2022-03-25 11:19:03 +0530957 countError("frame_windowupdate_zero_inc_conn")
kesavand2cde6582020-06-22 04:56:23 -0400958 return nil, ConnectionError(ErrCodeProtocol)
959 }
kesavandc71914f2022-03-25 11:19:03 +0530960 countError("frame_windowupdate_zero_inc_stream")
kesavand2cde6582020-06-22 04:56:23 -0400961 return nil, streamError(fh.StreamID, ErrCodeProtocol)
962 }
963 return &WindowUpdateFrame{
964 FrameHeader: fh,
965 Increment: inc,
966 }, nil
967}
968
969// WriteWindowUpdate writes a WINDOW_UPDATE frame.
970// The increment value must be between 1 and 2,147,483,647, inclusive.
971// If the Stream ID is zero, the window update applies to the
972// connection as a whole.
973func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
974 // "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
975 if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
976 return errors.New("illegal window increment value")
977 }
978 f.startWrite(FrameWindowUpdate, 0, streamID)
979 f.writeUint32(incr)
980 return f.endWrite()
981}
982
983// A HeadersFrame is used to open a stream and additionally carries a
984// header block fragment.
985type HeadersFrame struct {
986 FrameHeader
987
988 // Priority is set if FlagHeadersPriority is set in the FrameHeader.
989 Priority PriorityParam
990
991 headerFragBuf []byte // not owned
992}
993
994func (f *HeadersFrame) HeaderBlockFragment() []byte {
995 f.checkValid()
996 return f.headerFragBuf
997}
998
999func (f *HeadersFrame) HeadersEnded() bool {
1000 return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
1001}
1002
1003func (f *HeadersFrame) StreamEnded() bool {
1004 return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
1005}
1006
1007func (f *HeadersFrame) HasPriority() bool {
1008 return f.FrameHeader.Flags.Has(FlagHeadersPriority)
1009}
1010
kesavandc71914f2022-03-25 11:19:03 +05301011func parseHeadersFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
kesavand2cde6582020-06-22 04:56:23 -04001012 hf := &HeadersFrame{
1013 FrameHeader: fh,
1014 }
1015 if fh.StreamID == 0 {
1016 // HEADERS frames MUST be associated with a stream. If a HEADERS frame
1017 // is received whose stream identifier field is 0x0, the recipient MUST
1018 // respond with a connection error (Section 5.4.1) of type
1019 // PROTOCOL_ERROR.
kesavandc71914f2022-03-25 11:19:03 +05301020 countError("frame_headers_zero_stream")
kesavand2cde6582020-06-22 04:56:23 -04001021 return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
1022 }
1023 var padLength uint8
1024 if fh.Flags.Has(FlagHeadersPadded) {
1025 if p, padLength, err = readByte(p); err != nil {
kesavandc71914f2022-03-25 11:19:03 +05301026 countError("frame_headers_pad_short")
kesavand2cde6582020-06-22 04:56:23 -04001027 return
1028 }
1029 }
1030 if fh.Flags.Has(FlagHeadersPriority) {
1031 var v uint32
1032 p, v, err = readUint32(p)
1033 if err != nil {
kesavandc71914f2022-03-25 11:19:03 +05301034 countError("frame_headers_prio_short")
kesavand2cde6582020-06-22 04:56:23 -04001035 return nil, err
1036 }
1037 hf.Priority.StreamDep = v & 0x7fffffff
1038 hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
1039 p, hf.Priority.Weight, err = readByte(p)
1040 if err != nil {
kesavandc71914f2022-03-25 11:19:03 +05301041 countError("frame_headers_prio_weight_short")
kesavand2cde6582020-06-22 04:56:23 -04001042 return nil, err
1043 }
1044 }
kesavandc71914f2022-03-25 11:19:03 +05301045 if len(p)-int(padLength) < 0 {
1046 countError("frame_headers_pad_too_big")
kesavand2cde6582020-06-22 04:56:23 -04001047 return nil, streamError(fh.StreamID, ErrCodeProtocol)
1048 }
1049 hf.headerFragBuf = p[:len(p)-int(padLength)]
1050 return hf, nil
1051}
1052
1053// HeadersFrameParam are the parameters for writing a HEADERS frame.
1054type HeadersFrameParam struct {
1055 // StreamID is the required Stream ID to initiate.
1056 StreamID uint32
1057 // BlockFragment is part (or all) of a Header Block.
1058 BlockFragment []byte
1059
1060 // EndStream indicates that the header block is the last that
1061 // the endpoint will send for the identified stream. Setting
1062 // this flag causes the stream to enter one of "half closed"
1063 // states.
1064 EndStream bool
1065
1066 // EndHeaders indicates that this frame contains an entire
1067 // header block and is not followed by any
1068 // CONTINUATION frames.
1069 EndHeaders bool
1070
1071 // PadLength is the optional number of bytes of zeros to add
1072 // to this frame.
1073 PadLength uint8
1074
1075 // Priority, if non-zero, includes stream priority information
1076 // in the HEADER frame.
1077 Priority PriorityParam
1078}
1079
1080// WriteHeaders writes a single HEADERS frame.
1081//
1082// This is a low-level header writing method. Encoding headers and
1083// splitting them into any necessary CONTINUATION frames is handled
1084// elsewhere.
1085//
1086// It will perform exactly one Write to the underlying Writer.
1087// It is the caller's responsibility to not call other Write methods concurrently.
1088func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
1089 if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
1090 return errStreamID
1091 }
1092 var flags Flags
1093 if p.PadLength != 0 {
1094 flags |= FlagHeadersPadded
1095 }
1096 if p.EndStream {
1097 flags |= FlagHeadersEndStream
1098 }
1099 if p.EndHeaders {
1100 flags |= FlagHeadersEndHeaders
1101 }
1102 if !p.Priority.IsZero() {
1103 flags |= FlagHeadersPriority
1104 }
1105 f.startWrite(FrameHeaders, flags, p.StreamID)
1106 if p.PadLength != 0 {
1107 f.writeByte(p.PadLength)
1108 }
1109 if !p.Priority.IsZero() {
1110 v := p.Priority.StreamDep
1111 if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
1112 return errDepStreamID
1113 }
1114 if p.Priority.Exclusive {
1115 v |= 1 << 31
1116 }
1117 f.writeUint32(v)
1118 f.writeByte(p.Priority.Weight)
1119 }
1120 f.wbuf = append(f.wbuf, p.BlockFragment...)
1121 f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
1122 return f.endWrite()
1123}
1124
1125// A PriorityFrame specifies the sender-advised priority of a stream.
1126// See http://http2.github.io/http2-spec/#rfc.section.6.3
1127type PriorityFrame struct {
1128 FrameHeader
1129 PriorityParam
1130}
1131
1132// PriorityParam are the stream prioritzation parameters.
1133type PriorityParam struct {
1134 // StreamDep is a 31-bit stream identifier for the
1135 // stream that this stream depends on. Zero means no
1136 // dependency.
1137 StreamDep uint32
1138
1139 // Exclusive is whether the dependency is exclusive.
1140 Exclusive bool
1141
1142 // Weight is the stream's zero-indexed weight. It should be
1143 // set together with StreamDep, or neither should be set. Per
1144 // the spec, "Add one to the value to obtain a weight between
1145 // 1 and 256."
1146 Weight uint8
1147}
1148
1149func (p PriorityParam) IsZero() bool {
1150 return p == PriorityParam{}
1151}
1152
kesavandc71914f2022-03-25 11:19:03 +05301153func parsePriorityFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -04001154 if fh.StreamID == 0 {
kesavandc71914f2022-03-25 11:19:03 +05301155 countError("frame_priority_zero_stream")
kesavand2cde6582020-06-22 04:56:23 -04001156 return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
1157 }
1158 if len(payload) != 5 {
kesavandc71914f2022-03-25 11:19:03 +05301159 countError("frame_priority_bad_length")
kesavand2cde6582020-06-22 04:56:23 -04001160 return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
1161 }
1162 v := binary.BigEndian.Uint32(payload[:4])
1163 streamID := v & 0x7fffffff // mask off high bit
1164 return &PriorityFrame{
1165 FrameHeader: fh,
1166 PriorityParam: PriorityParam{
1167 Weight: payload[4],
1168 StreamDep: streamID,
1169 Exclusive: streamID != v, // was high bit set?
1170 },
1171 }, nil
1172}
1173
1174// WritePriority writes a PRIORITY frame.
1175//
1176// It will perform exactly one Write to the underlying Writer.
1177// It is the caller's responsibility to not call other Write methods concurrently.
1178func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
1179 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1180 return errStreamID
1181 }
1182 if !validStreamIDOrZero(p.StreamDep) {
1183 return errDepStreamID
1184 }
1185 f.startWrite(FramePriority, 0, streamID)
1186 v := p.StreamDep
1187 if p.Exclusive {
1188 v |= 1 << 31
1189 }
1190 f.writeUint32(v)
1191 f.writeByte(p.Weight)
1192 return f.endWrite()
1193}
1194
1195// A RSTStreamFrame allows for abnormal termination of a stream.
1196// See http://http2.github.io/http2-spec/#rfc.section.6.4
1197type RSTStreamFrame struct {
1198 FrameHeader
1199 ErrCode ErrCode
1200}
1201
kesavandc71914f2022-03-25 11:19:03 +05301202func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -04001203 if len(p) != 4 {
kesavandc71914f2022-03-25 11:19:03 +05301204 countError("frame_rststream_bad_len")
kesavand2cde6582020-06-22 04:56:23 -04001205 return nil, ConnectionError(ErrCodeFrameSize)
1206 }
1207 if fh.StreamID == 0 {
kesavandc71914f2022-03-25 11:19:03 +05301208 countError("frame_rststream_zero_stream")
kesavand2cde6582020-06-22 04:56:23 -04001209 return nil, ConnectionError(ErrCodeProtocol)
1210 }
1211 return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
1212}
1213
1214// WriteRSTStream writes a RST_STREAM frame.
1215//
1216// It will perform exactly one Write to the underlying Writer.
1217// It is the caller's responsibility to not call other Write methods concurrently.
1218func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
1219 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1220 return errStreamID
1221 }
1222 f.startWrite(FrameRSTStream, 0, streamID)
1223 f.writeUint32(uint32(code))
1224 return f.endWrite()
1225}
1226
1227// A ContinuationFrame is used to continue a sequence of header block fragments.
1228// See http://http2.github.io/http2-spec/#rfc.section.6.10
1229type ContinuationFrame struct {
1230 FrameHeader
1231 headerFragBuf []byte
1232}
1233
kesavandc71914f2022-03-25 11:19:03 +05301234func parseContinuationFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
kesavand2cde6582020-06-22 04:56:23 -04001235 if fh.StreamID == 0 {
kesavandc71914f2022-03-25 11:19:03 +05301236 countError("frame_continuation_zero_stream")
kesavand2cde6582020-06-22 04:56:23 -04001237 return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
1238 }
1239 return &ContinuationFrame{fh, p}, nil
1240}
1241
1242func (f *ContinuationFrame) HeaderBlockFragment() []byte {
1243 f.checkValid()
1244 return f.headerFragBuf
1245}
1246
1247func (f *ContinuationFrame) HeadersEnded() bool {
1248 return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
1249}
1250
1251// WriteContinuation writes a CONTINUATION frame.
1252//
1253// It will perform exactly one Write to the underlying Writer.
1254// It is the caller's responsibility to not call other Write methods concurrently.
1255func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
1256 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1257 return errStreamID
1258 }
1259 var flags Flags
1260 if endHeaders {
1261 flags |= FlagContinuationEndHeaders
1262 }
1263 f.startWrite(FrameContinuation, flags, streamID)
1264 f.wbuf = append(f.wbuf, headerBlockFragment...)
1265 return f.endWrite()
1266}
1267
1268// A PushPromiseFrame is used to initiate a server stream.
1269// See http://http2.github.io/http2-spec/#rfc.section.6.6
1270type PushPromiseFrame struct {
1271 FrameHeader
1272 PromiseID uint32
1273 headerFragBuf []byte // not owned
1274}
1275
1276func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
1277 f.checkValid()
1278 return f.headerFragBuf
1279}
1280
1281func (f *PushPromiseFrame) HeadersEnded() bool {
1282 return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
1283}
1284
kesavandc71914f2022-03-25 11:19:03 +05301285func parsePushPromise(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
kesavand2cde6582020-06-22 04:56:23 -04001286 pp := &PushPromiseFrame{
1287 FrameHeader: fh,
1288 }
1289 if pp.StreamID == 0 {
1290 // PUSH_PROMISE frames MUST be associated with an existing,
1291 // peer-initiated stream. The stream identifier of a
1292 // PUSH_PROMISE frame indicates the stream it is associated
1293 // with. If the stream identifier field specifies the value
1294 // 0x0, a recipient MUST respond with a connection error
1295 // (Section 5.4.1) of type PROTOCOL_ERROR.
kesavandc71914f2022-03-25 11:19:03 +05301296 countError("frame_pushpromise_zero_stream")
kesavand2cde6582020-06-22 04:56:23 -04001297 return nil, ConnectionError(ErrCodeProtocol)
1298 }
1299 // The PUSH_PROMISE frame includes optional padding.
1300 // Padding fields and flags are identical to those defined for DATA frames
1301 var padLength uint8
1302 if fh.Flags.Has(FlagPushPromisePadded) {
1303 if p, padLength, err = readByte(p); err != nil {
kesavandc71914f2022-03-25 11:19:03 +05301304 countError("frame_pushpromise_pad_short")
kesavand2cde6582020-06-22 04:56:23 -04001305 return
1306 }
1307 }
1308
1309 p, pp.PromiseID, err = readUint32(p)
1310 if err != nil {
kesavandc71914f2022-03-25 11:19:03 +05301311 countError("frame_pushpromise_promiseid_short")
kesavand2cde6582020-06-22 04:56:23 -04001312 return
1313 }
1314 pp.PromiseID = pp.PromiseID & (1<<31 - 1)
1315
1316 if int(padLength) > len(p) {
1317 // like the DATA frame, error out if padding is longer than the body.
kesavandc71914f2022-03-25 11:19:03 +05301318 countError("frame_pushpromise_pad_too_big")
kesavand2cde6582020-06-22 04:56:23 -04001319 return nil, ConnectionError(ErrCodeProtocol)
1320 }
1321 pp.headerFragBuf = p[:len(p)-int(padLength)]
1322 return pp, nil
1323}
1324
1325// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
1326type PushPromiseParam struct {
1327 // StreamID is the required Stream ID to initiate.
1328 StreamID uint32
1329
1330 // PromiseID is the required Stream ID which this
1331 // Push Promises
1332 PromiseID uint32
1333
1334 // BlockFragment is part (or all) of a Header Block.
1335 BlockFragment []byte
1336
1337 // EndHeaders indicates that this frame contains an entire
1338 // header block and is not followed by any
1339 // CONTINUATION frames.
1340 EndHeaders bool
1341
1342 // PadLength is the optional number of bytes of zeros to add
1343 // to this frame.
1344 PadLength uint8
1345}
1346
1347// WritePushPromise writes a single PushPromise Frame.
1348//
1349// As with Header Frames, This is the low level call for writing
1350// individual frames. Continuation frames are handled elsewhere.
1351//
1352// It will perform exactly one Write to the underlying Writer.
1353// It is the caller's responsibility to not call other Write methods concurrently.
1354func (f *Framer) WritePushPromise(p PushPromiseParam) error {
1355 if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
1356 return errStreamID
1357 }
1358 var flags Flags
1359 if p.PadLength != 0 {
1360 flags |= FlagPushPromisePadded
1361 }
1362 if p.EndHeaders {
1363 flags |= FlagPushPromiseEndHeaders
1364 }
1365 f.startWrite(FramePushPromise, flags, p.StreamID)
1366 if p.PadLength != 0 {
1367 f.writeByte(p.PadLength)
1368 }
1369 if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
1370 return errStreamID
1371 }
1372 f.writeUint32(p.PromiseID)
1373 f.wbuf = append(f.wbuf, p.BlockFragment...)
1374 f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
1375 return f.endWrite()
1376}
1377
1378// WriteRawFrame writes a raw frame. This can be used to write
1379// extension frames unknown to this package.
1380func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
1381 f.startWrite(t, flags, streamID)
1382 f.writeBytes(payload)
1383 return f.endWrite()
1384}
1385
1386func readByte(p []byte) (remain []byte, b byte, err error) {
1387 if len(p) == 0 {
1388 return nil, 0, io.ErrUnexpectedEOF
1389 }
1390 return p[1:], p[0], nil
1391}
1392
1393func readUint32(p []byte) (remain []byte, v uint32, err error) {
1394 if len(p) < 4 {
1395 return nil, 0, io.ErrUnexpectedEOF
1396 }
1397 return p[4:], binary.BigEndian.Uint32(p[:4]), nil
1398}
1399
1400type streamEnder interface {
1401 StreamEnded() bool
1402}
1403
1404type headersEnder interface {
1405 HeadersEnded() bool
1406}
1407
1408type headersOrContinuation interface {
1409 headersEnder
1410 HeaderBlockFragment() []byte
1411}
1412
1413// A MetaHeadersFrame is the representation of one HEADERS frame and
1414// zero or more contiguous CONTINUATION frames and the decoding of
1415// their HPACK-encoded contents.
1416//
1417// This type of frame does not appear on the wire and is only returned
1418// by the Framer when Framer.ReadMetaHeaders is set.
1419type MetaHeadersFrame struct {
1420 *HeadersFrame
1421
1422 // Fields are the fields contained in the HEADERS and
1423 // CONTINUATION frames. The underlying slice is owned by the
1424 // Framer and must not be retained after the next call to
1425 // ReadFrame.
1426 //
1427 // Fields are guaranteed to be in the correct http2 order and
1428 // not have unknown pseudo header fields or invalid header
1429 // field names or values. Required pseudo header fields may be
1430 // missing, however. Use the MetaHeadersFrame.Pseudo accessor
1431 // method access pseudo headers.
1432 Fields []hpack.HeaderField
1433
1434 // Truncated is whether the max header list size limit was hit
1435 // and Fields is incomplete. The hpack decoder state is still
1436 // valid, however.
1437 Truncated bool
1438}
1439
1440// PseudoValue returns the given pseudo header field's value.
1441// The provided pseudo field should not contain the leading colon.
1442func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string {
1443 for _, hf := range mh.Fields {
1444 if !hf.IsPseudo() {
1445 return ""
1446 }
1447 if hf.Name[1:] == pseudo {
1448 return hf.Value
1449 }
1450 }
1451 return ""
1452}
1453
1454// RegularFields returns the regular (non-pseudo) header fields of mh.
1455// The caller does not own the returned slice.
1456func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField {
1457 for i, hf := range mh.Fields {
1458 if !hf.IsPseudo() {
1459 return mh.Fields[i:]
1460 }
1461 }
1462 return nil
1463}
1464
1465// PseudoFields returns the pseudo header fields of mh.
1466// The caller does not own the returned slice.
1467func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
1468 for i, hf := range mh.Fields {
1469 if !hf.IsPseudo() {
1470 return mh.Fields[:i]
1471 }
1472 }
1473 return mh.Fields
1474}
1475
1476func (mh *MetaHeadersFrame) checkPseudos() error {
1477 var isRequest, isResponse bool
1478 pf := mh.PseudoFields()
1479 for i, hf := range pf {
1480 switch hf.Name {
1481 case ":method", ":path", ":scheme", ":authority":
1482 isRequest = true
1483 case ":status":
1484 isResponse = true
1485 default:
1486 return pseudoHeaderError(hf.Name)
1487 }
1488 // Check for duplicates.
1489 // This would be a bad algorithm, but N is 4.
1490 // And this doesn't allocate.
1491 for _, hf2 := range pf[:i] {
1492 if hf.Name == hf2.Name {
1493 return duplicatePseudoHeaderError(hf.Name)
1494 }
1495 }
1496 }
1497 if isRequest && isResponse {
1498 return errMixPseudoHeaderTypes
1499 }
1500 return nil
1501}
1502
1503func (fr *Framer) maxHeaderStringLen() int {
1504 v := fr.maxHeaderListSize()
1505 if uint32(int(v)) == v {
1506 return int(v)
1507 }
1508 // They had a crazy big number for MaxHeaderBytes anyway,
1509 // so give them unlimited header lengths:
1510 return 0
1511}
1512
1513// readMetaFrame returns 0 or more CONTINUATION frames from fr and
1514// merge them into the provided hf and returns a MetaHeadersFrame
1515// with the decoded hpack values.
1516func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
1517 if fr.AllowIllegalReads {
1518 return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
1519 }
1520 mh := &MetaHeadersFrame{
1521 HeadersFrame: hf,
1522 }
1523 var remainSize = fr.maxHeaderListSize()
1524 var sawRegular bool
1525
1526 var invalid error // pseudo header field errors
1527 hdec := fr.ReadMetaHeaders
1528 hdec.SetEmitEnabled(true)
1529 hdec.SetMaxStringLength(fr.maxHeaderStringLen())
1530 hdec.SetEmitFunc(func(hf hpack.HeaderField) {
1531 if VerboseLogs && fr.logReads {
1532 fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
1533 }
1534 if !httpguts.ValidHeaderFieldValue(hf.Value) {
1535 invalid = headerFieldValueError(hf.Value)
1536 }
1537 isPseudo := strings.HasPrefix(hf.Name, ":")
1538 if isPseudo {
1539 if sawRegular {
1540 invalid = errPseudoAfterRegular
1541 }
1542 } else {
1543 sawRegular = true
1544 if !validWireHeaderFieldName(hf.Name) {
1545 invalid = headerFieldNameError(hf.Name)
1546 }
1547 }
1548
1549 if invalid != nil {
1550 hdec.SetEmitEnabled(false)
1551 return
1552 }
1553
1554 size := hf.Size()
1555 if size > remainSize {
1556 hdec.SetEmitEnabled(false)
1557 mh.Truncated = true
1558 return
1559 }
1560 remainSize -= size
1561
1562 mh.Fields = append(mh.Fields, hf)
1563 })
1564 // Lose reference to MetaHeadersFrame:
1565 defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
1566
1567 var hc headersOrContinuation = hf
1568 for {
1569 frag := hc.HeaderBlockFragment()
1570 if _, err := hdec.Write(frag); err != nil {
1571 return nil, ConnectionError(ErrCodeCompression)
1572 }
1573
1574 if hc.HeadersEnded() {
1575 break
1576 }
1577 if f, err := fr.ReadFrame(); err != nil {
1578 return nil, err
1579 } else {
1580 hc = f.(*ContinuationFrame) // guaranteed by checkFrameOrder
1581 }
1582 }
1583
1584 mh.HeadersFrame.headerFragBuf = nil
1585 mh.HeadersFrame.invalidate()
1586
1587 if err := hdec.Close(); err != nil {
1588 return nil, ConnectionError(ErrCodeCompression)
1589 }
1590 if invalid != nil {
1591 fr.errDetail = invalid
1592 if VerboseLogs {
1593 log.Printf("http2: invalid header: %v", invalid)
1594 }
1595 return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
1596 }
1597 if err := mh.checkPseudos(); err != nil {
1598 fr.errDetail = err
1599 if VerboseLogs {
1600 log.Printf("http2: invalid pseudo headers: %v", err)
1601 }
1602 return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
1603 }
1604 return mh, nil
1605}
1606
1607func summarizeFrame(f Frame) string {
1608 var buf bytes.Buffer
1609 f.Header().writeDebug(&buf)
1610 switch f := f.(type) {
1611 case *SettingsFrame:
1612 n := 0
1613 f.ForeachSetting(func(s Setting) error {
1614 n++
1615 if n == 1 {
1616 buf.WriteString(", settings:")
1617 }
1618 fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
1619 return nil
1620 })
1621 if n > 0 {
1622 buf.Truncate(buf.Len() - 1) // remove trailing comma
1623 }
1624 case *DataFrame:
1625 data := f.Data()
1626 const max = 256
1627 if len(data) > max {
1628 data = data[:max]
1629 }
1630 fmt.Fprintf(&buf, " data=%q", data)
1631 if len(f.Data()) > max {
1632 fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
1633 }
1634 case *WindowUpdateFrame:
1635 if f.StreamID == 0 {
1636 buf.WriteString(" (conn)")
1637 }
1638 fmt.Fprintf(&buf, " incr=%v", f.Increment)
1639 case *PingFrame:
1640 fmt.Fprintf(&buf, " ping=%q", f.Data[:])
1641 case *GoAwayFrame:
1642 fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
1643 f.LastStreamID, f.ErrCode, f.debugData)
1644 case *RSTStreamFrame:
1645 fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
1646 }
1647 return buf.String()
1648}