mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-06 05:37:36 +03:00
implement parsing and writing of the H3_DATAGRAM setting
This commit is contained in:
parent
f68dfd5c3b
commit
aaf1d381d3
2 changed files with 85 additions and 11 deletions
|
@ -85,8 +85,11 @@ func (f *headersFrame) Write(b *bytes.Buffer) {
|
||||||
utils.WriteVarInt(b, f.Length)
|
utils.WriteVarInt(b, f.Length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const settingDatagram = 0x276
|
||||||
|
|
||||||
type settingsFrame struct {
|
type settingsFrame struct {
|
||||||
settings map[uint64]uint64
|
Datagram bool
|
||||||
|
other map[uint64]uint64 // all settings that we don't explicitly recognize
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
||||||
|
@ -100,8 +103,9 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
frame := &settingsFrame{settings: make(map[uint64]uint64)}
|
frame := &settingsFrame{}
|
||||||
b := bytes.NewReader(buf)
|
b := bytes.NewReader(buf)
|
||||||
|
var readDatagram bool
|
||||||
for b.Len() > 0 {
|
for b.Len() > 0 {
|
||||||
id, err := utils.ReadVarInt(b)
|
id, err := utils.ReadVarInt(b)
|
||||||
if err != nil { // should not happen. We allocated the whole frame already.
|
if err != nil { // should not happen. We allocated the whole frame already.
|
||||||
|
@ -111,10 +115,26 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
||||||
if err != nil { // should not happen. We allocated the whole frame already.
|
if err != nil { // should not happen. We allocated the whole frame already.
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if _, ok := frame.settings[id]; ok {
|
|
||||||
|
switch id {
|
||||||
|
case settingDatagram:
|
||||||
|
if readDatagram {
|
||||||
return nil, fmt.Errorf("duplicate setting: %d", id)
|
return nil, fmt.Errorf("duplicate setting: %d", id)
|
||||||
}
|
}
|
||||||
frame.settings[id] = val
|
readDatagram = true
|
||||||
|
if val != 0 && val != 1 {
|
||||||
|
return nil, fmt.Errorf("invalid value for H3_DATAGRAM: %d", val)
|
||||||
|
}
|
||||||
|
frame.Datagram = val == 1
|
||||||
|
default:
|
||||||
|
if _, ok := frame.other[id]; ok {
|
||||||
|
return nil, fmt.Errorf("duplicate setting: %d", id)
|
||||||
|
}
|
||||||
|
if frame.other == nil {
|
||||||
|
frame.other = make(map[uint64]uint64)
|
||||||
|
}
|
||||||
|
frame.other[id] = val
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return frame, nil
|
return frame, nil
|
||||||
}
|
}
|
||||||
|
@ -122,11 +142,18 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) {
|
||||||
func (f *settingsFrame) Write(b *bytes.Buffer) {
|
func (f *settingsFrame) Write(b *bytes.Buffer) {
|
||||||
utils.WriteVarInt(b, 0x4)
|
utils.WriteVarInt(b, 0x4)
|
||||||
var l protocol.ByteCount
|
var l protocol.ByteCount
|
||||||
for id, val := range f.settings {
|
for id, val := range f.other {
|
||||||
l += utils.VarIntLen(id) + utils.VarIntLen(val)
|
l += utils.VarIntLen(id) + utils.VarIntLen(val)
|
||||||
}
|
}
|
||||||
|
if f.Datagram {
|
||||||
|
l += utils.VarIntLen(settingDatagram) + utils.VarIntLen(1)
|
||||||
|
}
|
||||||
utils.WriteVarInt(b, uint64(l))
|
utils.WriteVarInt(b, uint64(l))
|
||||||
for id, val := range f.settings {
|
if f.Datagram {
|
||||||
|
utils.WriteVarInt(b, settingDatagram)
|
||||||
|
utils.WriteVarInt(b, 1)
|
||||||
|
}
|
||||||
|
for id, val := range f.other {
|
||||||
utils.WriteVarInt(b, id)
|
utils.WriteVarInt(b, id)
|
||||||
utils.WriteVarInt(b, val)
|
utils.WriteVarInt(b, val)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package http3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/internal/utils"
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
||||||
|
@ -84,8 +85,8 @@ var _ = Describe("Frames", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(frame).To(BeAssignableToTypeOf(&settingsFrame{}))
|
Expect(frame).To(BeAssignableToTypeOf(&settingsFrame{}))
|
||||||
sf := frame.(*settingsFrame)
|
sf := frame.(*settingsFrame)
|
||||||
Expect(sf.settings).To(HaveKeyWithValue(uint64(13), uint64(37)))
|
Expect(sf.other).To(HaveKeyWithValue(uint64(13), uint64(37)))
|
||||||
Expect(sf.settings).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef)))
|
Expect(sf.other).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef)))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("rejects duplicate settings", func() {
|
It("rejects duplicate settings", func() {
|
||||||
|
@ -101,7 +102,7 @@ var _ = Describe("Frames", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("writes", func() {
|
It("writes", func() {
|
||||||
sf := &settingsFrame{settings: map[uint64]uint64{
|
sf := &settingsFrame{other: map[uint64]uint64{
|
||||||
1: 2,
|
1: 2,
|
||||||
99: 999,
|
99: 999,
|
||||||
13: 37,
|
13: 37,
|
||||||
|
@ -114,7 +115,7 @@ var _ = Describe("Frames", func() {
|
||||||
})
|
})
|
||||||
|
|
||||||
It("errors on EOF", func() {
|
It("errors on EOF", func() {
|
||||||
sf := &settingsFrame{settings: map[uint64]uint64{
|
sf := &settingsFrame{other: map[uint64]uint64{
|
||||||
13: 37,
|
13: 37,
|
||||||
0xdeadbeef: 0xdecafbad,
|
0xdeadbeef: 0xdecafbad,
|
||||||
}}
|
}}
|
||||||
|
@ -132,5 +133,51 @@ var _ = Describe("Frames", func() {
|
||||||
Expect(err).To(MatchError(io.EOF))
|
Expect(err).To(MatchError(io.EOF))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("H3_DATAGRAM", func() {
|
||||||
|
It("reads the H3_DATAGRAM value", func() {
|
||||||
|
settings := appendVarInt(nil, settingDatagram)
|
||||||
|
settings = appendVarInt(settings, 1)
|
||||||
|
data := appendVarInt(nil, 4) // type byte
|
||||||
|
data = appendVarInt(data, uint64(len(settings)))
|
||||||
|
data = append(data, settings...)
|
||||||
|
f, err := parseNextFrame(bytes.NewReader(data))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(f).To(BeAssignableToTypeOf(&settingsFrame{}))
|
||||||
|
sf := f.(*settingsFrame)
|
||||||
|
Expect(sf.Datagram).To(BeTrue())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("rejects duplicate H3_DATAGRAM entries", func() {
|
||||||
|
settings := appendVarInt(nil, settingDatagram)
|
||||||
|
settings = appendVarInt(settings, 1)
|
||||||
|
settings = appendVarInt(settings, settingDatagram)
|
||||||
|
settings = appendVarInt(settings, 1)
|
||||||
|
data := appendVarInt(nil, 4) // type byte
|
||||||
|
data = appendVarInt(data, uint64(len(settings)))
|
||||||
|
data = append(data, settings...)
|
||||||
|
_, err := parseNextFrame(bytes.NewReader(data))
|
||||||
|
Expect(err).To(MatchError(fmt.Sprintf("duplicate setting: %d", settingDatagram)))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("rejects invalid values for the H3_DATAGRAM entry", func() {
|
||||||
|
settings := appendVarInt(nil, settingDatagram)
|
||||||
|
settings = appendVarInt(settings, 1337)
|
||||||
|
data := appendVarInt(nil, 4) // type byte
|
||||||
|
data = appendVarInt(data, uint64(len(settings)))
|
||||||
|
data = append(data, settings...)
|
||||||
|
_, err := parseNextFrame(bytes.NewReader(data))
|
||||||
|
Expect(err).To(MatchError("invalid value for H3_DATAGRAM: 1337"))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("writes the H3_DATAGRAM setting", func() {
|
||||||
|
sf := &settingsFrame{Datagram: true}
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
sf.Write(buf)
|
||||||
|
frame, err := parseNextFrame(buf)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(frame).To(Equal(sf))
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue