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