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