1
2
3
4
5 package http2
6
7 import (
8 "bytes"
9 "encoding/binary"
10 "errors"
11 "fmt"
12 "io"
13 "log"
14 "slices"
15 "strings"
16 "sync"
17
18 "net/http/internal/httpsfv"
19
20 "golang.org/x/net/http2/hpack"
21
22 "golang.org/x/net/http/httpguts"
23 )
24
25 const frameHeaderLen = 9
26
27 var padZeros = make([]byte, 255)
28
29
30
31
32 type FrameType uint8
33
34 const (
35 FrameData FrameType = 0x0
36 FrameHeaders FrameType = 0x1
37 FramePriority FrameType = 0x2
38 FrameRSTStream FrameType = 0x3
39 FrameSettings FrameType = 0x4
40 FramePushPromise FrameType = 0x5
41 FramePing FrameType = 0x6
42 FrameGoAway FrameType = 0x7
43 FrameWindowUpdate FrameType = 0x8
44 FrameContinuation FrameType = 0x9
45 FramePriorityUpdate FrameType = 0x10
46 )
47
48 var frameNames = [...]string{
49 FrameData: "DATA",
50 FrameHeaders: "HEADERS",
51 FramePriority: "PRIORITY",
52 FrameRSTStream: "RST_STREAM",
53 FrameSettings: "SETTINGS",
54 FramePushPromise: "PUSH_PROMISE",
55 FramePing: "PING",
56 FrameGoAway: "GOAWAY",
57 FrameWindowUpdate: "WINDOW_UPDATE",
58 FrameContinuation: "CONTINUATION",
59 FramePriorityUpdate: "PRIORITY_UPDATE",
60 }
61
62 func (t FrameType) String() string {
63 if int(t) < len(frameNames) {
64 return frameNames[t]
65 }
66 return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", t)
67 }
68
69
70
71 type Flags uint8
72
73
74 func (f Flags) Has(v Flags) bool {
75 return (f & v) == v
76 }
77
78
79 const (
80
81 FlagDataEndStream Flags = 0x1
82 FlagDataPadded Flags = 0x8
83
84
85 FlagHeadersEndStream Flags = 0x1
86 FlagHeadersEndHeaders Flags = 0x4
87 FlagHeadersPadded Flags = 0x8
88 FlagHeadersPriority Flags = 0x20
89
90
91 FlagSettingsAck Flags = 0x1
92
93
94 FlagPingAck Flags = 0x1
95
96
97 FlagContinuationEndHeaders Flags = 0x4
98
99 FlagPushPromiseEndHeaders Flags = 0x4
100 FlagPushPromisePadded Flags = 0x8
101 )
102
103 var flagName = map[FrameType]map[Flags]string{
104 FrameData: {
105 FlagDataEndStream: "END_STREAM",
106 FlagDataPadded: "PADDED",
107 },
108 FrameHeaders: {
109 FlagHeadersEndStream: "END_STREAM",
110 FlagHeadersEndHeaders: "END_HEADERS",
111 FlagHeadersPadded: "PADDED",
112 FlagHeadersPriority: "PRIORITY",
113 },
114 FrameSettings: {
115 FlagSettingsAck: "ACK",
116 },
117 FramePing: {
118 FlagPingAck: "ACK",
119 },
120 FrameContinuation: {
121 FlagContinuationEndHeaders: "END_HEADERS",
122 },
123 FramePushPromise: {
124 FlagPushPromiseEndHeaders: "END_HEADERS",
125 FlagPushPromisePadded: "PADDED",
126 },
127 }
128
129
130
131
132 type frameParser func(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error)
133
134 var frameParsers = [...]frameParser{
135 FrameData: parseDataFrame,
136 FrameHeaders: parseHeadersFrame,
137 FramePriority: parsePriorityFrame,
138 FrameRSTStream: parseRSTStreamFrame,
139 FrameSettings: parseSettingsFrame,
140 FramePushPromise: parsePushPromise,
141 FramePing: parsePingFrame,
142 FrameGoAway: parseGoAwayFrame,
143 FrameWindowUpdate: parseWindowUpdateFrame,
144 FrameContinuation: parseContinuationFrame,
145 FramePriorityUpdate: parsePriorityUpdateFrame,
146 }
147
148 func typeFrameParser(t FrameType) frameParser {
149 if int(t) < len(frameParsers) {
150 if f := frameParsers[t]; f != nil {
151 return f
152 }
153 }
154 return parseUnknownFrame
155 }
156
157
158
159
160 type FrameHeader struct {
161 valid bool
162
163
164
165
166 Type FrameType
167
168
169
170 Flags Flags
171
172
173
174
175 Length uint32
176
177
178
179 StreamID uint32
180 }
181
182
183
184 func (h FrameHeader) Header() FrameHeader { return h }
185
186 func (h FrameHeader) String() string {
187 var buf bytes.Buffer
188 buf.WriteString("[FrameHeader ")
189 h.writeDebug(&buf)
190 buf.WriteByte(']')
191 return buf.String()
192 }
193
194 func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
195 buf.WriteString(h.Type.String())
196 if h.Flags != 0 {
197 buf.WriteString(" flags=")
198 set := 0
199 for i := uint8(0); i < 8; i++ {
200 if h.Flags&(1<<i) == 0 {
201 continue
202 }
203 set++
204 if set > 1 {
205 buf.WriteByte('|')
206 }
207 name := flagName[h.Type][Flags(1<<i)]
208 if name != "" {
209 buf.WriteString(name)
210 } else {
211 fmt.Fprintf(buf, "0x%x", 1<<i)
212 }
213 }
214 }
215 if h.StreamID != 0 {
216 fmt.Fprintf(buf, " stream=%d", h.StreamID)
217 }
218 fmt.Fprintf(buf, " len=%d", h.Length)
219 }
220
221 func (h *FrameHeader) checkValid() {
222 if !h.valid {
223 panic("Frame accessor called on non-owned Frame")
224 }
225 }
226
227 func (h *FrameHeader) invalidate() { h.valid = false }
228
229
230
231 var fhBytes = sync.Pool{
232 New: func() interface{} {
233 buf := make([]byte, frameHeaderLen)
234 return &buf
235 },
236 }
237
238 func invalidHTTP1LookingFrameHeader() FrameHeader {
239 fh, _ := readFrameHeader(make([]byte, frameHeaderLen), strings.NewReader("HTTP/1.1 "))
240 return fh
241 }
242
243
244
245 func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
246 bufp := fhBytes.Get().(*[]byte)
247 defer fhBytes.Put(bufp)
248 return readFrameHeader(*bufp, r)
249 }
250
251 func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
252 _, err := io.ReadFull(r, buf[:frameHeaderLen])
253 if err != nil {
254 return FrameHeader{}, err
255 }
256 return FrameHeader{
257 Length: (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
258 Type: FrameType(buf[3]),
259 Flags: Flags(buf[4]),
260 StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
261 valid: true,
262 }, nil
263 }
264
265
266
267
268
269
270 type Frame interface {
271 Header() FrameHeader
272
273
274
275
276 invalidate()
277 }
278
279
280 type Framer struct {
281 r io.Reader
282 lastFrame Frame
283 errDetail error
284
285
286
287
288 countError func(errToken string)
289
290
291
292 lastHeaderStream uint32
293
294 lastFrameType FrameType
295
296 maxReadSize uint32
297 headerBuf [frameHeaderLen]byte
298
299
300
301
302 getReadBuf func(size uint32) []byte
303 readBuf []byte
304
305 maxWriteSize uint32
306
307 w io.Writer
308 wbuf []byte
309
310
311
312
313
314
315
316 AllowIllegalWrites bool
317
318
319
320
321
322
323 AllowIllegalReads bool
324
325
326
327
328 ReadMetaHeaders *hpack.Decoder
329
330
331
332
333
334 MaxHeaderListSize uint32
335
336
337
338
339
340
341
342 logReads, logWrites bool
343
344 debugFramer *Framer
345 debugFramerBuf *bytes.Buffer
346 debugReadLoggerf func(string, ...interface{})
347 debugWriteLoggerf func(string, ...interface{})
348
349 frameCache *frameCache
350 }
351
352 func (fr *Framer) maxHeaderListSize() uint32 {
353 if fr.MaxHeaderListSize == 0 {
354 return 16 << 20
355 }
356 return fr.MaxHeaderListSize
357 }
358
359 func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
360
361 f.wbuf = append(f.wbuf[:0],
362 0,
363 0,
364 0,
365 byte(ftype),
366 byte(flags),
367 byte(streamID>>24),
368 byte(streamID>>16),
369 byte(streamID>>8),
370 byte(streamID))
371 }
372
373 func (f *Framer) endWrite() error {
374
375
376 length := len(f.wbuf) - frameHeaderLen
377 if length >= (1 << 24) {
378 return ErrFrameTooLarge
379 }
380 _ = append(f.wbuf[:0],
381 byte(length>>16),
382 byte(length>>8),
383 byte(length))
384 if f.logWrites {
385 f.logWrite()
386 }
387
388 n, err := f.w.Write(f.wbuf)
389 if err == nil && n != len(f.wbuf) {
390 err = io.ErrShortWrite
391 }
392 return err
393 }
394
395 func (f *Framer) logWrite() {
396 if f.debugFramer == nil {
397 f.debugFramerBuf = new(bytes.Buffer)
398 f.debugFramer = NewFramer(nil, f.debugFramerBuf)
399 f.debugFramer.logReads = false
400
401
402 f.debugFramer.AllowIllegalReads = true
403 }
404 f.debugFramerBuf.Write(f.wbuf)
405 fr, err := f.debugFramer.ReadFrame()
406 if err != nil {
407 f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
408 return
409 }
410 f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
411 }
412
413 func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
414 func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
415 func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
416 func (f *Framer) writeUint32(v uint32) {
417 f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
418 }
419
420 const (
421 minMaxFrameSize = 1 << 14
422 maxFrameSize = 1<<24 - 1
423 )
424
425
426
427
428 func (fr *Framer) SetReuseFrames() {
429 if fr.frameCache != nil {
430 return
431 }
432 fr.frameCache = &frameCache{}
433 }
434
435 type frameCache struct {
436 dataFrame DataFrame
437 }
438
439 func (fc *frameCache) getDataFrame() *DataFrame {
440 if fc == nil {
441 return &DataFrame{}
442 }
443 return &fc.dataFrame
444 }
445
446
447 func NewFramer(w io.Writer, r io.Reader) *Framer {
448 fr := &Framer{
449 w: w,
450 r: r,
451 countError: func(string) {},
452 logReads: logFrameReads,
453 logWrites: logFrameWrites,
454 debugReadLoggerf: log.Printf,
455 debugWriteLoggerf: log.Printf,
456 }
457 fr.getReadBuf = func(size uint32) []byte {
458 if cap(fr.readBuf) >= int(size) {
459 return fr.readBuf[:size]
460 }
461 fr.readBuf = make([]byte, size)
462 return fr.readBuf
463 }
464 fr.SetMaxReadFrameSize(maxFrameSize)
465 return fr
466 }
467
468
469
470
471
472 func (fr *Framer) SetMaxReadFrameSize(v uint32) {
473 if v > maxFrameSize {
474 v = maxFrameSize
475 }
476 fr.maxReadSize = v
477 }
478
479
480
481
482
483
484
485
486 func (fr *Framer) ErrorDetail() error {
487 return fr.errDetail
488 }
489
490
491
492 var ErrFrameTooLarge = errors.New("http2: frame too large")
493
494
495
496 func terminalReadFrameError(err error) bool {
497 if _, ok := err.(StreamError); ok {
498 return false
499 }
500 return err != nil
501 }
502
503
504
505
506
507
508
509
510
511
512
513 func (fr *Framer) ReadFrameHeader() (FrameHeader, error) {
514 fr.errDetail = nil
515 fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
516 if err != nil {
517 return fh, err
518 }
519 if fh.Length > fr.maxReadSize {
520 if fh == invalidHTTP1LookingFrameHeader() {
521 return fh, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", ErrFrameTooLarge)
522 }
523 return fh, ErrFrameTooLarge
524 }
525 if err := fr.checkFrameOrder(fh); err != nil {
526 return fh, err
527 }
528 return fh, nil
529 }
530
531
532
533
534
535 func (fr *Framer) ReadFrameForHeader(fh FrameHeader) (Frame, error) {
536 if fr.lastFrame != nil {
537 fr.lastFrame.invalidate()
538 }
539 payload := fr.getReadBuf(fh.Length)
540 if _, err := io.ReadFull(fr.r, payload); err != nil {
541 if fh == invalidHTTP1LookingFrameHeader() {
542 return nil, fmt.Errorf("http2: failed reading the frame payload: %w, note that the frame header looked like an HTTP/1.1 header", err)
543 }
544 return nil, err
545 }
546 f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, fr.countError, payload)
547 if err != nil {
548 if ce, ok := err.(connError); ok {
549 return nil, fr.connError(ce.Code, ce.Reason)
550 }
551 return nil, err
552 }
553 fr.lastFrame = f
554 if fr.logReads {
555 fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
556 }
557 if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil {
558 return fr.readMetaFrame(f.(*HeadersFrame))
559 }
560 return f, nil
561 }
562
563
564
565
566
567
568
569
570
571
572
573 func (fr *Framer) ReadFrame() (Frame, error) {
574 fh, err := fr.ReadFrameHeader()
575 if err != nil {
576 return nil, err
577 }
578 return fr.ReadFrameForHeader(fh)
579 }
580
581
582
583
584
585 func (fr *Framer) connError(code ErrCode, reason string) error {
586 fr.errDetail = errors.New(reason)
587 return ConnectionError(code)
588 }
589
590
591
592
593 func (fr *Framer) checkFrameOrder(fh FrameHeader) error {
594 lastType := fr.lastFrameType
595 fr.lastFrameType = fh.Type
596 if fr.AllowIllegalReads {
597 return nil
598 }
599
600 if fr.lastHeaderStream != 0 {
601 if fh.Type != FrameContinuation {
602 return fr.connError(ErrCodeProtocol,
603 fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
604 fh.Type, fh.StreamID,
605 lastType, fr.lastHeaderStream))
606 }
607 if fh.StreamID != fr.lastHeaderStream {
608 return fr.connError(ErrCodeProtocol,
609 fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
610 fh.StreamID, fr.lastHeaderStream))
611 }
612 } else if fh.Type == FrameContinuation {
613 return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
614 }
615
616 switch fh.Type {
617 case FrameHeaders, FrameContinuation:
618 if fh.Flags.Has(FlagHeadersEndHeaders) {
619 fr.lastHeaderStream = 0
620 } else {
621 fr.lastHeaderStream = fh.StreamID
622 }
623 }
624
625 return nil
626 }
627
628
629
630
631 type DataFrame struct {
632 FrameHeader
633 data []byte
634 }
635
636 func (f *DataFrame) StreamEnded() bool {
637 return f.FrameHeader.Flags.Has(FlagDataEndStream)
638 }
639
640
641
642
643
644 func (f *DataFrame) Data() []byte {
645 f.checkValid()
646 return f.data
647 }
648
649 func parseDataFrame(fc *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
650 if fh.StreamID == 0 {
651
652
653
654
655
656 countError("frame_data_stream_0")
657 return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
658 }
659 f := fc.getDataFrame()
660 f.FrameHeader = fh
661
662 var padSize byte
663 if fh.Flags.Has(FlagDataPadded) {
664 var err error
665 payload, padSize, err = readByte(payload)
666 if err != nil {
667 countError("frame_data_pad_byte_short")
668 return nil, err
669 }
670 }
671 if int(padSize) > len(payload) {
672
673
674
675
676 countError("frame_data_pad_too_big")
677 return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
678 }
679 f.data = payload[:len(payload)-int(padSize)]
680 return f, nil
681 }
682
683 var (
684 errStreamID = errors.New("invalid stream ID")
685 errDepStreamID = errors.New("invalid dependent stream ID")
686 errPadLength = errors.New("pad length too large")
687 errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
688 )
689
690 func validStreamIDOrZero(streamID uint32) bool {
691 return streamID&(1<<31) == 0
692 }
693
694 func validStreamID(streamID uint32) bool {
695 return streamID != 0 && streamID&(1<<31) == 0
696 }
697
698
699
700
701
702
703 func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
704 return f.WriteDataPadded(streamID, endStream, data, nil)
705 }
706
707
708
709
710
711
712
713
714
715
716 func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
717 if err := f.startWriteDataPadded(streamID, endStream, data, pad); err != nil {
718 return err
719 }
720 return f.endWrite()
721 }
722
723
724
725 func (f *Framer) startWriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
726 if !validStreamID(streamID) && !f.AllowIllegalWrites {
727 return errStreamID
728 }
729 if len(pad) > 0 {
730 if len(pad) > 255 {
731 return errPadLength
732 }
733 if !f.AllowIllegalWrites {
734 for _, b := range pad {
735 if b != 0 {
736
737 return errPadBytes
738 }
739 }
740 }
741 }
742 var flags Flags
743 if endStream {
744 flags |= FlagDataEndStream
745 }
746 if pad != nil {
747 flags |= FlagDataPadded
748 }
749 f.startWrite(FrameData, flags, streamID)
750 if pad != nil {
751 f.wbuf = append(f.wbuf, byte(len(pad)))
752 }
753 f.wbuf = append(f.wbuf, data...)
754 f.wbuf = append(f.wbuf, pad...)
755 return nil
756 }
757
758
759
760
761
762
763 type SettingsFrame struct {
764 FrameHeader
765 p []byte
766 }
767
768 func parseSettingsFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
769 if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
770
771
772
773
774
775
776 countError("frame_settings_ack_with_length")
777 return nil, ConnectionError(ErrCodeFrameSize)
778 }
779 if fh.StreamID != 0 {
780
781
782
783
784
785
786
787 countError("frame_settings_has_stream")
788 return nil, ConnectionError(ErrCodeProtocol)
789 }
790 if len(p)%6 != 0 {
791 countError("frame_settings_mod_6")
792
793 return nil, ConnectionError(ErrCodeFrameSize)
794 }
795 f := &SettingsFrame{FrameHeader: fh, p: p}
796 if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
797 countError("frame_settings_window_size_too_big")
798
799
800
801 return nil, ConnectionError(ErrCodeFlowControl)
802 }
803 return f, nil
804 }
805
806 func (f *SettingsFrame) IsAck() bool {
807 return f.FrameHeader.Flags.Has(FlagSettingsAck)
808 }
809
810 func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
811 f.checkValid()
812 for i := 0; i < f.NumSettings(); i++ {
813 if s := f.Setting(i); s.ID == id {
814 return s.Val, true
815 }
816 }
817 return 0, false
818 }
819
820
821
822 func (f *SettingsFrame) Setting(i int) Setting {
823 buf := f.p
824 return Setting{
825 ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
826 Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
827 }
828 }
829
830 func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
831
832
833 func (f *SettingsFrame) HasDuplicates() bool {
834 num := f.NumSettings()
835 if num == 0 {
836 return false
837 }
838
839
840 if num < 10 {
841 for i := 0; i < num; i++ {
842 idi := f.Setting(i).ID
843 for j := i + 1; j < num; j++ {
844 idj := f.Setting(j).ID
845 if idi == idj {
846 return true
847 }
848 }
849 }
850 return false
851 }
852 seen := map[SettingID]bool{}
853 for i := 0; i < num; i++ {
854 id := f.Setting(i).ID
855 if seen[id] {
856 return true
857 }
858 seen[id] = true
859 }
860 return false
861 }
862
863
864
865 func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
866 f.checkValid()
867 for i := 0; i < f.NumSettings(); i++ {
868 if err := fn(f.Setting(i)); err != nil {
869 return err
870 }
871 }
872 return nil
873 }
874
875
876
877
878
879
880 func (f *Framer) WriteSettings(settings ...Setting) error {
881 f.startWrite(FrameSettings, 0, 0)
882 for _, s := range settings {
883 f.writeUint16(uint16(s.ID))
884 f.writeUint32(s.Val)
885 }
886 return f.endWrite()
887 }
888
889
890
891
892
893 func (f *Framer) WriteSettingsAck() error {
894 f.startWrite(FrameSettings, FlagSettingsAck, 0)
895 return f.endWrite()
896 }
897
898
899
900
901
902 type PingFrame struct {
903 FrameHeader
904 Data [8]byte
905 }
906
907 func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
908
909 func parsePingFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
910 if len(payload) != 8 {
911 countError("frame_ping_length")
912 return nil, ConnectionError(ErrCodeFrameSize)
913 }
914 if fh.StreamID != 0 {
915 countError("frame_ping_has_stream")
916 return nil, ConnectionError(ErrCodeProtocol)
917 }
918 f := &PingFrame{FrameHeader: fh}
919 copy(f.Data[:], payload)
920 return f, nil
921 }
922
923 func (f *Framer) WritePing(ack bool, data [8]byte) error {
924 var flags Flags
925 if ack {
926 flags = FlagPingAck
927 }
928 f.startWrite(FramePing, flags, 0)
929 f.writeBytes(data[:])
930 return f.endWrite()
931 }
932
933
934
935 type GoAwayFrame struct {
936 FrameHeader
937 LastStreamID uint32
938 ErrCode ErrCode
939 debugData []byte
940 }
941
942
943
944
945
946 func (f *GoAwayFrame) DebugData() []byte {
947 f.checkValid()
948 return f.debugData
949 }
950
951 func parseGoAwayFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
952 if fh.StreamID != 0 {
953 countError("frame_goaway_has_stream")
954 return nil, ConnectionError(ErrCodeProtocol)
955 }
956 if len(p) < 8 {
957 countError("frame_goaway_short")
958 return nil, ConnectionError(ErrCodeFrameSize)
959 }
960 return &GoAwayFrame{
961 FrameHeader: fh,
962 LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
963 ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])),
964 debugData: p[8:],
965 }, nil
966 }
967
968 func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
969 f.startWrite(FrameGoAway, 0, 0)
970 f.writeUint32(maxStreamID & (1<<31 - 1))
971 f.writeUint32(uint32(code))
972 f.writeBytes(debugData)
973 return f.endWrite()
974 }
975
976
977
978 type UnknownFrame struct {
979 FrameHeader
980 p []byte
981 }
982
983
984
985
986
987
988 func (f *UnknownFrame) Payload() []byte {
989 f.checkValid()
990 return f.p
991 }
992
993 func parseUnknownFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
994 return &UnknownFrame{fh, p}, nil
995 }
996
997
998
999 type WindowUpdateFrame struct {
1000 FrameHeader
1001 Increment uint32
1002 }
1003
1004 func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
1005 if len(p) != 4 {
1006 countError("frame_windowupdate_bad_len")
1007 return nil, ConnectionError(ErrCodeFrameSize)
1008 }
1009 inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff
1010 if inc == 0 {
1011
1012
1013
1014
1015
1016
1017 if fh.StreamID == 0 {
1018 countError("frame_windowupdate_zero_inc_conn")
1019 return nil, ConnectionError(ErrCodeProtocol)
1020 }
1021 countError("frame_windowupdate_zero_inc_stream")
1022 return nil, streamError(fh.StreamID, ErrCodeProtocol)
1023 }
1024 return &WindowUpdateFrame{
1025 FrameHeader: fh,
1026 Increment: inc,
1027 }, nil
1028 }
1029
1030
1031
1032
1033
1034 func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
1035
1036 if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
1037 return errors.New("illegal window increment value")
1038 }
1039 f.startWrite(FrameWindowUpdate, 0, streamID)
1040 f.writeUint32(incr)
1041 return f.endWrite()
1042 }
1043
1044
1045
1046 type HeadersFrame struct {
1047 FrameHeader
1048
1049
1050 Priority PriorityParam
1051
1052 headerFragBuf []byte
1053 }
1054
1055 func (f *HeadersFrame) HeaderBlockFragment() []byte {
1056 f.checkValid()
1057 return f.headerFragBuf
1058 }
1059
1060 func (f *HeadersFrame) HeadersEnded() bool {
1061 return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
1062 }
1063
1064 func (f *HeadersFrame) StreamEnded() bool {
1065 return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
1066 }
1067
1068 func (f *HeadersFrame) HasPriority() bool {
1069 return f.FrameHeader.Flags.Has(FlagHeadersPriority)
1070 }
1071
1072 func parseHeadersFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
1073 hf := &HeadersFrame{
1074 FrameHeader: fh,
1075 }
1076 if fh.StreamID == 0 {
1077
1078
1079
1080
1081 countError("frame_headers_zero_stream")
1082 return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
1083 }
1084 var padLength uint8
1085 if fh.Flags.Has(FlagHeadersPadded) {
1086 if p, padLength, err = readByte(p); err != nil {
1087 countError("frame_headers_pad_short")
1088 return
1089 }
1090 }
1091 if fh.Flags.Has(FlagHeadersPriority) {
1092 var v uint32
1093 p, v, err = readUint32(p)
1094 if err != nil {
1095 countError("frame_headers_prio_short")
1096 return nil, err
1097 }
1098 hf.Priority.StreamDep = v & 0x7fffffff
1099 hf.Priority.Exclusive = (v != hf.Priority.StreamDep)
1100 p, hf.Priority.Weight, err = readByte(p)
1101 if err != nil {
1102 countError("frame_headers_prio_weight_short")
1103 return nil, err
1104 }
1105 }
1106 if len(p)-int(padLength) < 0 {
1107 countError("frame_headers_pad_too_big")
1108 return nil, streamError(fh.StreamID, ErrCodeProtocol)
1109 }
1110 hf.headerFragBuf = p[:len(p)-int(padLength)]
1111 return hf, nil
1112 }
1113
1114
1115 type HeadersFrameParam struct {
1116
1117 StreamID uint32
1118
1119 BlockFragment []byte
1120
1121
1122
1123
1124
1125 EndStream bool
1126
1127
1128
1129
1130 EndHeaders bool
1131
1132
1133
1134 PadLength uint8
1135
1136
1137
1138 Priority PriorityParam
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149 func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
1150 if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
1151 return errStreamID
1152 }
1153 var flags Flags
1154 if p.PadLength != 0 {
1155 flags |= FlagHeadersPadded
1156 }
1157 if p.EndStream {
1158 flags |= FlagHeadersEndStream
1159 }
1160 if p.EndHeaders {
1161 flags |= FlagHeadersEndHeaders
1162 }
1163 if !p.Priority.IsZero() {
1164 flags |= FlagHeadersPriority
1165 }
1166 f.startWrite(FrameHeaders, flags, p.StreamID)
1167 if p.PadLength != 0 {
1168 f.writeByte(p.PadLength)
1169 }
1170 if !p.Priority.IsZero() {
1171 v := p.Priority.StreamDep
1172 if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
1173 return errDepStreamID
1174 }
1175 if p.Priority.Exclusive {
1176 v |= 1 << 31
1177 }
1178 f.writeUint32(v)
1179 f.writeByte(p.Priority.Weight)
1180 }
1181 f.wbuf = append(f.wbuf, p.BlockFragment...)
1182 f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
1183 return f.endWrite()
1184 }
1185
1186
1187
1188 type PriorityFrame struct {
1189 FrameHeader
1190 PriorityParam
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210 func defaultRFC9218Priority(canUseDefault bool) PriorityParam {
1211 if canUseDefault {
1212 return PriorityParam{
1213 urgency: 3,
1214 incremental: 0,
1215 }
1216 }
1217 return PriorityParam{
1218 urgency: 3,
1219 incremental: 1,
1220 }
1221 }
1222
1223
1224
1225
1226
1227
1228 type PriorityParam struct {
1229
1230
1231
1232 StreamDep uint32
1233
1234
1235 Exclusive bool
1236
1237
1238
1239
1240
1241 Weight uint8
1242
1243
1244
1245
1246 urgency uint8
1247
1248
1249
1250
1251
1252
1253
1254
1255 incremental uint8
1256 }
1257
1258 func (p PriorityParam) IsZero() bool {
1259 return p == PriorityParam{}
1260 }
1261
1262 func parsePriorityFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
1263 if fh.StreamID == 0 {
1264 countError("frame_priority_zero_stream")
1265 return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
1266 }
1267 if len(payload) != 5 {
1268 countError("frame_priority_bad_length")
1269 return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
1270 }
1271 v := binary.BigEndian.Uint32(payload[:4])
1272 streamID := v & 0x7fffffff
1273 return &PriorityFrame{
1274 FrameHeader: fh,
1275 PriorityParam: PriorityParam{
1276 Weight: payload[4],
1277 StreamDep: streamID,
1278 Exclusive: streamID != v,
1279 },
1280 }, nil
1281 }
1282
1283
1284
1285
1286
1287 func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
1288 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1289 return errStreamID
1290 }
1291 if !validStreamIDOrZero(p.StreamDep) {
1292 return errDepStreamID
1293 }
1294 f.startWrite(FramePriority, 0, streamID)
1295 v := p.StreamDep
1296 if p.Exclusive {
1297 v |= 1 << 31
1298 }
1299 f.writeUint32(v)
1300 f.writeByte(p.Weight)
1301 return f.endWrite()
1302 }
1303
1304
1305
1306 type PriorityUpdateFrame struct {
1307 FrameHeader
1308 Priority string
1309 PrioritizedStreamID uint32
1310 }
1311
1312 func parseRFC9218Priority(s string, canUseDefault bool) (p PriorityParam, ok bool) {
1313 p = defaultRFC9218Priority(canUseDefault)
1314 ok = httpsfv.ParseDictionary(s, func(key, val, _ string) {
1315 switch key {
1316 case "u":
1317 if u, ok := httpsfv.ParseInteger(val); ok && u >= 0 && u <= 7 {
1318 p.urgency = uint8(u)
1319 }
1320 case "i":
1321 if i, ok := httpsfv.ParseBoolean(val); ok {
1322 if i {
1323 p.incremental = 1
1324 } else {
1325 p.incremental = 0
1326 }
1327 }
1328 }
1329 })
1330 if !ok {
1331 return defaultRFC9218Priority(canUseDefault), ok
1332 }
1333 return p, true
1334 }
1335
1336 func parsePriorityUpdateFrame(_ *frameCache, fh FrameHeader, countError func(string), payload []byte) (Frame, error) {
1337 if fh.StreamID != 0 {
1338 countError("frame_priority_update_non_zero_stream")
1339 return nil, connError{ErrCodeProtocol, "PRIORITY_UPDATE frame with non-zero stream ID"}
1340 }
1341 if len(payload) < 4 {
1342 countError("frame_priority_update_bad_length")
1343 return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY_UPDATE frame payload size was %d; want at least 4", len(payload))}
1344 }
1345 v := binary.BigEndian.Uint32(payload[:4])
1346 streamID := v & 0x7fffffff
1347 if streamID == 0 {
1348 countError("frame_priority_update_prioritizing_zero_stream")
1349 return nil, connError{ErrCodeProtocol, "PRIORITY_UPDATE frame with prioritized stream ID of zero"}
1350 }
1351 return &PriorityUpdateFrame{
1352 FrameHeader: fh,
1353 PrioritizedStreamID: streamID,
1354 Priority: string(payload[4:]),
1355 }, nil
1356 }
1357
1358
1359
1360
1361
1362 func (f *Framer) WritePriorityUpdate(streamID uint32, priority string) error {
1363 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1364 return errStreamID
1365 }
1366 f.startWrite(FramePriorityUpdate, 0, 0)
1367 f.writeUint32(streamID)
1368 f.writeBytes([]byte(priority))
1369 return f.endWrite()
1370 }
1371
1372
1373
1374 type RSTStreamFrame struct {
1375 FrameHeader
1376 ErrCode ErrCode
1377 }
1378
1379 func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
1380 if len(p) != 4 {
1381 countError("frame_rststream_bad_len")
1382 return nil, ConnectionError(ErrCodeFrameSize)
1383 }
1384 if fh.StreamID == 0 {
1385 countError("frame_rststream_zero_stream")
1386 return nil, ConnectionError(ErrCodeProtocol)
1387 }
1388 return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
1389 }
1390
1391
1392
1393
1394
1395 func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
1396 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1397 return errStreamID
1398 }
1399 f.startWrite(FrameRSTStream, 0, streamID)
1400 f.writeUint32(uint32(code))
1401 return f.endWrite()
1402 }
1403
1404
1405
1406 type ContinuationFrame struct {
1407 FrameHeader
1408 headerFragBuf []byte
1409 }
1410
1411 func parseContinuationFrame(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (Frame, error) {
1412 if fh.StreamID == 0 {
1413 countError("frame_continuation_zero_stream")
1414 return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
1415 }
1416 return &ContinuationFrame{fh, p}, nil
1417 }
1418
1419 func (f *ContinuationFrame) HeaderBlockFragment() []byte {
1420 f.checkValid()
1421 return f.headerFragBuf
1422 }
1423
1424 func (f *ContinuationFrame) HeadersEnded() bool {
1425 return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
1426 }
1427
1428
1429
1430
1431
1432 func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
1433 if !validStreamID(streamID) && !f.AllowIllegalWrites {
1434 return errStreamID
1435 }
1436 var flags Flags
1437 if endHeaders {
1438 flags |= FlagContinuationEndHeaders
1439 }
1440 f.startWrite(FrameContinuation, flags, streamID)
1441 f.wbuf = append(f.wbuf, headerBlockFragment...)
1442 return f.endWrite()
1443 }
1444
1445
1446
1447 type PushPromiseFrame struct {
1448 FrameHeader
1449 PromiseID uint32
1450 headerFragBuf []byte
1451 }
1452
1453 func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
1454 f.checkValid()
1455 return f.headerFragBuf
1456 }
1457
1458 func (f *PushPromiseFrame) HeadersEnded() bool {
1459 return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
1460 }
1461
1462 func parsePushPromise(_ *frameCache, fh FrameHeader, countError func(string), p []byte) (_ Frame, err error) {
1463 pp := &PushPromiseFrame{
1464 FrameHeader: fh,
1465 }
1466 if pp.StreamID == 0 {
1467
1468
1469
1470
1471
1472
1473 countError("frame_pushpromise_zero_stream")
1474 return nil, ConnectionError(ErrCodeProtocol)
1475 }
1476
1477
1478 var padLength uint8
1479 if fh.Flags.Has(FlagPushPromisePadded) {
1480 if p, padLength, err = readByte(p); err != nil {
1481 countError("frame_pushpromise_pad_short")
1482 return
1483 }
1484 }
1485
1486 p, pp.PromiseID, err = readUint32(p)
1487 if err != nil {
1488 countError("frame_pushpromise_promiseid_short")
1489 return
1490 }
1491 pp.PromiseID = pp.PromiseID & (1<<31 - 1)
1492
1493 if int(padLength) > len(p) {
1494
1495 countError("frame_pushpromise_pad_too_big")
1496 return nil, ConnectionError(ErrCodeProtocol)
1497 }
1498 pp.headerFragBuf = p[:len(p)-int(padLength)]
1499 return pp, nil
1500 }
1501
1502
1503 type PushPromiseParam struct {
1504
1505 StreamID uint32
1506
1507
1508
1509 PromiseID uint32
1510
1511
1512 BlockFragment []byte
1513
1514
1515
1516
1517 EndHeaders bool
1518
1519
1520
1521 PadLength uint8
1522 }
1523
1524
1525
1526
1527
1528
1529
1530
1531 func (f *Framer) WritePushPromise(p PushPromiseParam) error {
1532 if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
1533 return errStreamID
1534 }
1535 var flags Flags
1536 if p.PadLength != 0 {
1537 flags |= FlagPushPromisePadded
1538 }
1539 if p.EndHeaders {
1540 flags |= FlagPushPromiseEndHeaders
1541 }
1542 f.startWrite(FramePushPromise, flags, p.StreamID)
1543 if p.PadLength != 0 {
1544 f.writeByte(p.PadLength)
1545 }
1546 if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
1547 return errStreamID
1548 }
1549 f.writeUint32(p.PromiseID)
1550 f.wbuf = append(f.wbuf, p.BlockFragment...)
1551 f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
1552 return f.endWrite()
1553 }
1554
1555
1556
1557 func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
1558 f.startWrite(t, flags, streamID)
1559 f.writeBytes(payload)
1560 return f.endWrite()
1561 }
1562
1563 func readByte(p []byte) (remain []byte, b byte, err error) {
1564 if len(p) == 0 {
1565 return nil, 0, io.ErrUnexpectedEOF
1566 }
1567 return p[1:], p[0], nil
1568 }
1569
1570 func readUint32(p []byte) (remain []byte, v uint32, err error) {
1571 if len(p) < 4 {
1572 return nil, 0, io.ErrUnexpectedEOF
1573 }
1574 return p[4:], binary.BigEndian.Uint32(p[:4]), nil
1575 }
1576
1577 type streamEnder interface {
1578 StreamEnded() bool
1579 }
1580
1581 type headersEnder interface {
1582 HeadersEnded() bool
1583 }
1584
1585 type headersOrContinuation interface {
1586 headersEnder
1587 HeaderBlockFragment() []byte
1588 }
1589
1590
1591
1592
1593
1594
1595
1596 type MetaHeadersFrame struct {
1597 *HeadersFrame
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609 Fields []hpack.HeaderField
1610
1611
1612
1613
1614 Truncated bool
1615 }
1616
1617
1618
1619 func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string {
1620 for _, hf := range mh.Fields {
1621 if !hf.IsPseudo() {
1622 return ""
1623 }
1624 if hf.Name[1:] == pseudo {
1625 return hf.Value
1626 }
1627 }
1628 return ""
1629 }
1630
1631
1632
1633 func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField {
1634 for i, hf := range mh.Fields {
1635 if !hf.IsPseudo() {
1636 return mh.Fields[i:]
1637 }
1638 }
1639 return nil
1640 }
1641
1642
1643
1644 func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
1645 for i, hf := range mh.Fields {
1646 if !hf.IsPseudo() {
1647 return mh.Fields[:i]
1648 }
1649 }
1650 return mh.Fields
1651 }
1652
1653 func (mh *MetaHeadersFrame) rfc9218Priority(priorityAware bool) (p PriorityParam, priorityAwareAfter, hasIntermediary bool) {
1654 var s string
1655 for _, field := range mh.Fields {
1656 if field.Name == "priority" {
1657 s = field.Value
1658 priorityAware = true
1659 }
1660 if slices.Contains([]string{"via", "forwarded", "x-forwarded-for"}, field.Name) {
1661 hasIntermediary = true
1662 }
1663 }
1664
1665
1666 p, _ = parseRFC9218Priority(s, priorityAware && !hasIntermediary)
1667 return p, priorityAware, hasIntermediary
1668 }
1669
1670 func (mh *MetaHeadersFrame) checkPseudos() error {
1671 var isRequest, isResponse bool
1672 pf := mh.PseudoFields()
1673 for i, hf := range pf {
1674 switch hf.Name {
1675 case ":method", ":path", ":scheme", ":authority", ":protocol":
1676 isRequest = true
1677 case ":status":
1678 isResponse = true
1679 default:
1680 return pseudoHeaderError(hf.Name)
1681 }
1682
1683
1684
1685 for _, hf2 := range pf[:i] {
1686 if hf.Name == hf2.Name {
1687 return duplicatePseudoHeaderError(hf.Name)
1688 }
1689 }
1690 }
1691 if isRequest && isResponse {
1692 return errMixPseudoHeaderTypes
1693 }
1694 return nil
1695 }
1696
1697 func (fr *Framer) maxHeaderStringLen() int {
1698 v := int(fr.maxHeaderListSize())
1699 if v < 0 {
1700
1701 return 0
1702 }
1703 return v
1704 }
1705
1706
1707
1708
1709 func (fr *Framer) readMetaFrame(hf *HeadersFrame) (Frame, error) {
1710 if fr.AllowIllegalReads {
1711 return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
1712 }
1713 mh := &MetaHeadersFrame{
1714 HeadersFrame: hf,
1715 }
1716 var remainSize = fr.maxHeaderListSize()
1717 var sawRegular bool
1718
1719 var invalid error
1720 hdec := fr.ReadMetaHeaders
1721 hdec.SetEmitEnabled(true)
1722 hdec.SetMaxStringLength(fr.maxHeaderStringLen())
1723 hdec.SetEmitFunc(func(hf hpack.HeaderField) {
1724 if VerboseLogs && fr.logReads {
1725 fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
1726 }
1727 if !httpguts.ValidHeaderFieldValue(hf.Value) {
1728
1729 invalid = headerFieldValueError(hf.Name)
1730 }
1731 isPseudo := strings.HasPrefix(hf.Name, ":")
1732 if isPseudo {
1733 if sawRegular {
1734 invalid = errPseudoAfterRegular
1735 }
1736 } else {
1737 sawRegular = true
1738 if !validWireHeaderFieldName(hf.Name) {
1739 invalid = headerFieldNameError(hf.Name)
1740 }
1741 }
1742
1743 if invalid != nil {
1744 hdec.SetEmitEnabled(false)
1745 return
1746 }
1747
1748 size := hf.Size()
1749 if size > remainSize {
1750 hdec.SetEmitEnabled(false)
1751 mh.Truncated = true
1752 remainSize = 0
1753 return
1754 }
1755 remainSize -= size
1756
1757 mh.Fields = append(mh.Fields, hf)
1758 })
1759
1760 defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
1761
1762 var hc headersOrContinuation = hf
1763 for {
1764 frag := hc.HeaderBlockFragment()
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774 if int64(len(frag)) > int64(2*remainSize) {
1775 if VerboseLogs {
1776 log.Printf("http2: header list too large")
1777 }
1778
1779
1780 return mh, ConnectionError(ErrCodeProtocol)
1781 }
1782
1783
1784
1785
1786 if invalid != nil {
1787 if VerboseLogs {
1788 log.Printf("http2: invalid header: %v", invalid)
1789 }
1790
1791
1792 return mh, ConnectionError(ErrCodeProtocol)
1793 }
1794
1795 if _, err := hdec.Write(frag); err != nil {
1796 return mh, ConnectionError(ErrCodeCompression)
1797 }
1798
1799 if hc.HeadersEnded() {
1800 break
1801 }
1802 if f, err := fr.ReadFrame(); err != nil {
1803 return nil, err
1804 } else {
1805 hc = f.(*ContinuationFrame)
1806 }
1807 }
1808
1809 mh.HeadersFrame.headerFragBuf = nil
1810 mh.HeadersFrame.invalidate()
1811
1812 if err := hdec.Close(); err != nil {
1813 return mh, ConnectionError(ErrCodeCompression)
1814 }
1815 if invalid != nil {
1816 fr.errDetail = invalid
1817 if VerboseLogs {
1818 log.Printf("http2: invalid header: %v", invalid)
1819 }
1820 return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
1821 }
1822 if err := mh.checkPseudos(); err != nil {
1823 fr.errDetail = err
1824 if VerboseLogs {
1825 log.Printf("http2: invalid pseudo headers: %v", err)
1826 }
1827 return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
1828 }
1829 return mh, nil
1830 }
1831
1832 func summarizeFrame(f Frame) string {
1833 var buf bytes.Buffer
1834 f.Header().writeDebug(&buf)
1835 switch f := f.(type) {
1836 case *SettingsFrame:
1837 n := 0
1838 f.ForeachSetting(func(s Setting) error {
1839 n++
1840 if n == 1 {
1841 buf.WriteString(", settings:")
1842 }
1843 fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
1844 return nil
1845 })
1846 if n > 0 {
1847 buf.Truncate(buf.Len() - 1)
1848 }
1849 case *DataFrame:
1850 data := f.Data()
1851 const max = 256
1852 if len(data) > max {
1853 data = data[:max]
1854 }
1855 fmt.Fprintf(&buf, " data=%q", data)
1856 if len(f.Data()) > max {
1857 fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
1858 }
1859 case *WindowUpdateFrame:
1860 if f.StreamID == 0 {
1861 buf.WriteString(" (conn)")
1862 }
1863 fmt.Fprintf(&buf, " incr=%v", f.Increment)
1864 case *PingFrame:
1865 fmt.Fprintf(&buf, " ping=%q", f.Data[:])
1866 case *GoAwayFrame:
1867 fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
1868 f.LastStreamID, f.ErrCode, f.debugData)
1869 case *RSTStreamFrame:
1870 fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
1871 }
1872 return buf.String()
1873 }
1874
View as plain text