From a54816867f96fea1a4176a2ded078a7599415b66 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Tue, 22 Mar 2022 10:22:15 +0100 Subject: [PATCH] make it possible to set settings unknown to the http3 package --- http3/client.go | 3 ++- http3/client_test.go | 2 +- http3/frames.go | 14 +++++++------- http3/frames_test.go | 8 ++++---- http3/request_test.go | 2 +- http3/roundtrip.go | 4 ++++ http3/server.go | 9 +++++++-- http3/server_test.go | 2 +- 8 files changed, 27 insertions(+), 17 deletions(-) diff --git a/http3/client.go b/http3/client.go index afd50dd20..bf12ecd17 100644 --- a/http3/client.go +++ b/http3/client.go @@ -42,6 +42,7 @@ type roundTripperOpts struct { DisableCompression bool EnableDatagram bool MaxHeaderBytes int64 + AdditionalSettings map[uint64]uint64 } // client is a HTTP3 client doing requests @@ -130,7 +131,7 @@ func (c *client) setupConn() error { buf := &bytes.Buffer{} quicvarint.Write(buf, streamTypeControlStream) // send the SETTINGS frame - (&settingsFrame{Datagram: c.opts.EnableDatagram}).Write(buf) + (&settingsFrame{Datagram: c.opts.EnableDatagram, Other: c.opts.AdditionalSettings}).Write(buf) _, err = str.Write(buf.Bytes()) return err } diff --git a/http3/client_test.go b/http3/client_test.go index 0cab46d07..28733ac0c 100644 --- a/http3/client_test.go +++ b/http3/client_test.go @@ -261,7 +261,7 @@ var _ = Describe("Client", func() { }) } - It("resets streams other than the control stream and the QPACK streams", func() { + It("resets streams Other than the control stream and the QPACK streams", func() { buf := &bytes.Buffer{} quicvarint.Write(buf, 1337) str := mockquic.NewMockStream(mockCtrl) diff --git a/http3/frames.go b/http3/frames.go index 36029b9e4..c1225b8df 100644 --- a/http3/frames.go +++ b/http3/frames.go @@ -70,7 +70,7 @@ const settingDatagram = 0xffd277 type settingsFrame struct { Datagram bool - other map[uint64]uint64 // all settings that we don't explicitly recognize + Other map[uint64]uint64 // all settings that we don't explicitly recognize } func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) { @@ -108,13 +108,13 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) { } frame.Datagram = val == 1 default: - if _, ok := frame.other[id]; ok { + if _, ok := frame.Other[id]; ok { return nil, fmt.Errorf("duplicate setting: %d", id) } - if frame.other == nil { - frame.other = make(map[uint64]uint64) + if frame.Other == nil { + frame.Other = make(map[uint64]uint64) } - frame.other[id] = val + frame.Other[id] = val } } return frame, nil @@ -123,7 +123,7 @@ func parseSettingsFrame(r io.Reader, l uint64) (*settingsFrame, error) { func (f *settingsFrame) Write(b *bytes.Buffer) { quicvarint.Write(b, 0x4) var l protocol.ByteCount - for id, val := range f.other { + for id, val := range f.Other { l += quicvarint.Len(id) + quicvarint.Len(val) } if f.Datagram { @@ -134,7 +134,7 @@ func (f *settingsFrame) Write(b *bytes.Buffer) { quicvarint.Write(b, settingDatagram) quicvarint.Write(b, 1) } - for id, val := range f.other { + for id, val := range f.Other { quicvarint.Write(b, id) quicvarint.Write(b, val) } diff --git a/http3/frames_test.go b/http3/frames_test.go index 83f65370b..014b6a4a3 100644 --- a/http3/frames_test.go +++ b/http3/frames_test.go @@ -85,8 +85,8 @@ var _ = Describe("Frames", func() { Expect(err).ToNot(HaveOccurred()) Expect(frame).To(BeAssignableToTypeOf(&settingsFrame{})) sf := frame.(*settingsFrame) - Expect(sf.other).To(HaveKeyWithValue(uint64(13), uint64(37))) - Expect(sf.other).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef))) + Expect(sf.Other).To(HaveKeyWithValue(uint64(13), uint64(37))) + Expect(sf.Other).To(HaveKeyWithValue(uint64(0xdead), uint64(0xbeef))) }) It("rejects duplicate settings", func() { @@ -102,7 +102,7 @@ var _ = Describe("Frames", func() { }) It("writes", func() { - sf := &settingsFrame{other: map[uint64]uint64{ + sf := &settingsFrame{Other: map[uint64]uint64{ 1: 2, 99: 999, 13: 37, @@ -115,7 +115,7 @@ var _ = Describe("Frames", func() { }) It("errors on EOF", func() { - sf := &settingsFrame{other: map[uint64]uint64{ + sf := &settingsFrame{Other: map[uint64]uint64{ 13: 37, 0xdeadbeef: 0xdecafbad, }} diff --git a/http3/request_test.go b/http3/request_test.go index e430dc4e8..006cc0be7 100644 --- a/http3/request_test.go +++ b/http3/request_test.go @@ -64,7 +64,7 @@ var _ = Describe("Request", func() { })) }) - It("handles other headers", func() { + It("handles Other headers", func() { headers := []qpack.HeaderField{ {Name: ":path", Value: "/foo"}, {Name: ":authority", Value: "quic.clemente.io"}, diff --git a/http3/roundtrip.go b/http3/roundtrip.go index 156fddabe..f9c0c3944 100644 --- a/http3/roundtrip.go +++ b/http3/roundtrip.go @@ -47,6 +47,10 @@ type RoundTripper struct { // See https://www.ietf.org/archive/id/draft-schinazi-masque-h3-datagram-02.html. EnableDatagrams bool + // Additional HTTP/3 settings. + // It is invalid to specify any settings defined by the HTTP/3 draft and the datagram draft. + AdditionalSettings map[uint64]uint64 + // Dial specifies an optional dial function for creating QUIC // connections for requests. // If Dial is nil, quic.DialAddrEarlyContext will be used. diff --git a/http3/server.go b/http3/server.go index 84a34c4b3..1873f895f 100644 --- a/http3/server.go +++ b/http3/server.go @@ -140,9 +140,14 @@ type Server struct { // a port different from the port the Server is listening on. Port int + // Additional HTTP/3 settings. + // It is invalid to specify any settings defined by the HTTP/3 draft and the datagram draft. + AdditionalSettings map[uint64]uint64 + mutex sync.RWMutex listeners map[*quic.EarlyListener]listenerInfo - closed utils.AtomicBool + + closed utils.AtomicBool altSvcHeader string @@ -345,7 +350,7 @@ func (s *Server) handleConn(conn quic.EarlyConnection) { } buf := &bytes.Buffer{} quicvarint.Write(buf, streamTypeControlStream) // stream type - (&settingsFrame{Datagram: s.EnableDatagrams}).Write(buf) + (&settingsFrame{Datagram: s.EnableDatagrams, Other: s.AdditionalSettings}).Write(buf) str.Write(buf.Bytes()) go s.handleUnidirectionalStreams(conn) diff --git a/http3/server_test.go b/http3/server_test.go index 0007b97a2..2c722e65d 100644 --- a/http3/server_test.go +++ b/http3/server_test.go @@ -296,7 +296,7 @@ var _ = Describe("Server", func() { }) } - It("reset streams other than the control stream and the QPACK streams", func() { + It("reset streams Other than the control stream and the QPACK streams", func() { buf := &bytes.Buffer{} quicvarint.Write(buf, 1337) str := mockquic.NewMockStream(mockCtrl)