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