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