github.com/ooni/psiphon/tunnel-core@v0.0.0-20230105123940-fe12a24c96ee/oovendor/quic-go/http3/frames.go (about) 1 package http3 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "io/ioutil" 8 9 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/internal/protocol" 10 "github.com/ooni/psiphon/tunnel-core/oovendor/quic-go/quicvarint" 11 ) 12 13 type frame interface{} 14 15 func parseNextFrame(r io.Reader) (frame, error) { 16 qr := quicvarint.NewReader(r) 17 for { 18 t, err := quicvarint.Read(qr) 19 if err != nil { 20 return nil, err 21 } 22 l, err := quicvarint.Read(qr) 23 if err != nil { 24 return nil, err 25 } 26 27 switch t { 28 case 0x0: 29 return &dataFrame{Length: l}, nil 30 case 0x1: 31 return &headersFrame{Length: l}, nil 32 case 0x4: 33 return parseSettingsFrame(r, l) 34 case 0x3: // CANCEL_PUSH 35 fallthrough 36 case 0x5: // PUSH_PROMISE 37 fallthrough 38 case 0x7: // GOAWAY 39 fallthrough 40 case 0xd: // MAX_PUSH_ID 41 fallthrough 42 case 0xe: // DUPLICATE_PUSH 43 fallthrough 44 default: 45 // skip over unknown frames 46 if _, err := io.CopyN(ioutil.Discard, qr, int64(l)); err != nil { 47 return nil, err 48 } 49 } 50 } 51 } 52 53 type dataFrame struct { 54 Length uint64 55 } 56 57 func (f *dataFrame) Write(b *bytes.Buffer) { 58 quicvarint.Write(b, 0x0) 59 quicvarint.Write(b, f.Length) 60 } 61 62 type headersFrame struct { 63 Length uint64 64 } 65 66 func (f *headersFrame) Write(b *bytes.Buffer) { 67 quicvarint.Write(b, 0x1) 68 quicvarint.Write(b, f.Length) 69 } 70 71 const settingDatagram = 0x276 72 73 type settingsFrame struct { 74 Datagram bool 75 other map[uint64]uint64 // all settings that we don't explicitly recognize 76 } 77 78 func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) { 79 if l > 8*(1<<10) { 80 return nil, fmt.Errorf("unexpected size for SETTINGS frame: %d", l) 81 } 82 buf := make([]byte, l) 83 if _, err := io.ReadFull(r, buf); err != nil { 84 if err == io.ErrUnexpectedEOF { 85 return nil, io.EOF 86 } 87 return nil, err 88 } 89 frame := &settingsFrame{} 90 b := bytes.NewReader(buf) 91 var readDatagram bool 92 for b.Len() > 0 { 93 id, err := quicvarint.Read(b) 94 if err != nil { // should not happen. We allocated the whole frame already. 95 return nil, err 96 } 97 val, err := quicvarint.Read(b) 98 if err != nil { // should not happen. We allocated the whole frame already. 99 return nil, err 100 } 101 102 switch id { 103 case settingDatagram: 104 if readDatagram { 105 return nil, fmt.Errorf("duplicate setting: %d", id) 106 } 107 readDatagram = true 108 if val != 0 && val != 1 { 109 return nil, fmt.Errorf("invalid value for H3_DATAGRAM: %d", val) 110 } 111 frame.Datagram = val == 1 112 default: 113 if _, ok := frame.other[id]; ok { 114 return nil, fmt.Errorf("duplicate setting: %d", id) 115 } 116 if frame.other == nil { 117 frame.other = make(map[uint64]uint64) 118 } 119 frame.other[id] = val 120 } 121 } 122 return frame, nil 123 } 124 125 func (f *settingsFrame) Write(b *bytes.Buffer) { 126 quicvarint.Write(b, 0x4) 127 var l protocol.ByteCount 128 for id, val := range f.other { 129 l += quicvarint.Len(id) + quicvarint.Len(val) 130 } 131 if f.Datagram { 132 l += quicvarint.Len(settingDatagram) + quicvarint.Len(1) 133 } 134 quicvarint.Write(b, uint64(l)) 135 if f.Datagram { 136 quicvarint.Write(b, settingDatagram) 137 quicvarint.Write(b, 1) 138 } 139 for id, val := range f.other { 140 quicvarint.Write(b, id) 141 quicvarint.Write(b, val) 142 } 143 }