diff --git a/client.go b/client.go index 6c389b9a..70e490b0 100644 --- a/client.go +++ b/client.go @@ -402,8 +402,8 @@ func (c *client) createNewTLSSession(version protocol.VersionNumber) error { InitialMaxStreamDataUni: protocol.InitialMaxStreamData, InitialMaxData: protocol.InitialMaxData, IdleTimeout: c.config.IdleTimeout, - MaxBidiStreams: uint16(c.config.MaxIncomingStreams), - MaxUniStreams: uint16(c.config.MaxIncomingUniStreams), + MaxBidiStreams: uint64(c.config.MaxIncomingStreams), + MaxUniStreams: uint64(c.config.MaxIncomingUniStreams), DisableMigration: true, } diff --git a/interface.go b/interface.go index f9e4f06e..2567144f 100644 --- a/interface.go +++ b/interface.go @@ -185,12 +185,10 @@ type Config struct { // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open. // If not set, it will default to 100. // If set to a negative value, it doesn't allow any bidirectional streams. - // Values larger than 65535 (math.MaxUint16) are invalid. MaxIncomingStreams int // MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open. // If not set, it will default to 100. // If set to a negative value, it doesn't allow any unidirectional streams. - // Values larger than 65535 (math.MaxUint16) are invalid. MaxIncomingUniStreams int // KeepAlive defines whether this peer will periodically send PING frames to keep the connection alive. KeepAlive bool diff --git a/internal/handshake/transport_parameter_test.go b/internal/handshake/transport_parameter_test.go index 7ed94ffc..9f0241ae 100644 --- a/internal/handshake/transport_parameter_test.go +++ b/internal/handshake/transport_parameter_test.go @@ -2,7 +2,8 @@ package handshake import ( "bytes" - "fmt" + "math" + "math/rand" "time" "github.com/lucas-clemente/quic-go/internal/protocol" @@ -25,172 +26,135 @@ var _ = Describe("Transport Parameters", func() { Expect(p.String()).To(Equal("&handshake.TransportParameters{InitialMaxStreamDataBidiLocal: 0x1234, InitialMaxStreamDataBidiRemote: 0x2345, InitialMaxStreamDataUni: 0x3456, InitialMaxData: 0x4567, MaxBidiStreams: 1337, MaxUniStreams: 7331, IdleTimeout: 42s}")) }) - Context("parsing", func() { - var ( - params *TransportParameters - parameters map[transportParameterID][]byte - statelessResetToken []byte - ) + getRandomValue := func() uint64 { + maxVals := []int64{math.MaxUint8 / 4, math.MaxUint16 / 4, math.MaxUint32 / 4, math.MaxUint64 / 4} + rand.Seed(GinkgoRandomSeed()) + return uint64(rand.Int63n(maxVals[int(rand.Int31n(4))])) + } - marshal := func(p map[transportParameterID][]byte) []byte { - b := &bytes.Buffer{} - for id, val := range p { - utils.BigEndian.WriteUint16(b, uint16(id)) - utils.BigEndian.WriteUint16(b, uint16(len(val))) - b.Write(val) - } - return b.Bytes() + It("marshals und unmarshals", func() { + params := &TransportParameters{ + InitialMaxStreamDataBidiLocal: protocol.ByteCount(getRandomValue()), + InitialMaxStreamDataBidiRemote: protocol.ByteCount(getRandomValue()), + InitialMaxStreamDataUni: protocol.ByteCount(getRandomValue()), + InitialMaxData: protocol.ByteCount(getRandomValue()), + IdleTimeout: 0xcafe * time.Second, + MaxBidiStreams: getRandomValue(), + MaxUniStreams: getRandomValue(), + DisableMigration: true, + StatelessResetToken: bytes.Repeat([]byte{100}, 16), } + b := &bytes.Buffer{} + params.marshal(b) - BeforeEach(func() { - params = &TransportParameters{} - statelessResetToken = bytes.Repeat([]byte{42}, 16) - parameters = map[transportParameterID][]byte{ - initialMaxStreamDataBidiLocalParameterID: {0x11, 0x22, 0x33, 0x44}, - initialMaxStreamDataBidiRemoteParameterID: {0x22, 0x33, 0x44, 0x55}, - initialMaxStreamDataUniParameterID: {0x33, 0x44, 0x55, 0x66}, - initialMaxDataParameterID: {0x44, 0x55, 0x66, 0x77}, - initialMaxBidiStreamsParameterID: {0x33, 0x44}, - initialMaxUniStreamsParameterID: {0x44, 0x55}, - idleTimeoutParameterID: {0x13, 0x37}, - maxPacketSizeParameterID: {0x73, 0x31}, - disableMigrationParameterID: {}, - statelessResetTokenParameterID: statelessResetToken, - } - }) - It("reads parameters", func() { - Expect(params.unmarshal(marshal(parameters))).To(Succeed()) - Expect(params.InitialMaxStreamDataBidiLocal).To(Equal(protocol.ByteCount(0x11223344))) - Expect(params.InitialMaxStreamDataBidiRemote).To(Equal(protocol.ByteCount(0x22334455))) - Expect(params.InitialMaxStreamDataUni).To(Equal(protocol.ByteCount(0x33445566))) - Expect(params.InitialMaxData).To(Equal(protocol.ByteCount(0x44556677))) - Expect(params.MaxBidiStreams).To(Equal(uint16(0x3344))) - Expect(params.MaxUniStreams).To(Equal(uint16(0x4455))) - Expect(params.IdleTimeout).To(Equal(0x1337 * time.Second)) - Expect(params.MaxPacketSize).To(Equal(protocol.ByteCount(0x7331))) - Expect(params.DisableMigration).To(BeTrue()) - Expect(params.StatelessResetToken).To(Equal(statelessResetToken)) - }) - - It("errors if a parameter is sent twice", func() { - data := marshal(parameters) - parameters = map[transportParameterID][]byte{ - maxPacketSizeParameterID: {0x73, 0x31}, - } - data = append(data, marshal(parameters)...) - err := params.unmarshal(data) - Expect(err).To(MatchError(fmt.Sprintf("received duplicate transport parameter %#x", maxPacketSizeParameterID))) - }) - - It("doesn't allow values below the minimum remote idle timeout", func() { - t := 2 * time.Second - Expect(t).To(BeNumerically("<", protocol.MinRemoteIdleTimeout)) - parameters[idleTimeoutParameterID] = []byte{0, uint8(t.Seconds())} - err := params.unmarshal(marshal(parameters)) - Expect(err).ToNot(HaveOccurred()) - Expect(params.IdleTimeout).To(Equal(protocol.MinRemoteIdleTimeout)) - }) - - It("rejects the parameters if the initial_max_stream_data_bidi_local has the wrong length", func() { - parameters[initialMaxStreamDataBidiLocalParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_stream_data_bidi_local: 3 (expected 4)")) - }) - - It("rejects the parameters if the initial_max_stream_data_bidi_remote has the wrong length", func() { - parameters[initialMaxStreamDataBidiRemoteParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_stream_data_bidi_remote: 3 (expected 4)")) - }) - - It("rejects the parameters if the initial_max_stream_data_uni has the wrong length", func() { - parameters[initialMaxStreamDataUniParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_stream_data_uni: 3 (expected 4)")) - }) - - It("rejects the parameters if the initial_max_data has the wrong length", func() { - parameters[initialMaxDataParameterID] = []byte{0x11, 0x22, 0x33} // should be 4 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_data: 3 (expected 4)")) - }) - - It("rejects the parameters if the initial_max_stream_id_bidi has the wrong length", func() { - parameters[initialMaxBidiStreamsParameterID] = []byte{0x11, 0x22, 0x33} // should be 2 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_stream_id_bidi: 3 (expected 2)")) - }) - - It("rejects the parameters if the initial_max_stream_id_bidi has the wrong length", func() { - parameters[initialMaxUniStreamsParameterID] = []byte{0x11, 0x22, 0x33} // should be 2 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for initial_max_stream_id_uni: 3 (expected 2)")) - }) - - It("rejects the parameters if the initial_idle_timeout has the wrong length", func() { - parameters[idleTimeoutParameterID] = []byte{0x11, 0x22, 0x33} // should be 2 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for idle_timeout: 3 (expected 2)")) - }) - - It("rejects the parameters if max_packet_size has the wrong length", func() { - parameters[maxPacketSizeParameterID] = []byte{0x11} // should be 2 bytes - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for max_packet_size: 1 (expected 2)")) - }) - - It("rejects max_packet_sizes smaller than 1200 bytes", func() { - parameters[maxPacketSizeParameterID] = []byte{0x4, 0xaf} // 0x4af = 1199 - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("invalid value for max_packet_size: 1199 (minimum 1200)")) - }) - - It("rejects the parameters if disable_connection_migration has the wrong length", func() { - parameters[disableMigrationParameterID] = []byte{0x11} // should empty - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for disable_migration: 1 (expected empty)")) - }) - - It("rejects the parameters if the stateless_reset_token has the wrong length", func() { - parameters[statelessResetTokenParameterID] = statelessResetToken[1:] - err := params.unmarshal(marshal(parameters)) - Expect(err).To(MatchError("wrong length for stateless_reset_token: 15 (expected 16)")) - }) - - It("ignores unknown parameters", func() { - parameters[1337] = []byte{42} - err := params.unmarshal(marshal(parameters)) - Expect(err).ToNot(HaveOccurred()) - }) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(Succeed()) + Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal)) + Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote)) + Expect(p.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni)) + Expect(p.InitialMaxData).To(Equal(params.InitialMaxData)) + Expect(p.MaxUniStreams).To(Equal(params.MaxUniStreams)) + Expect(p.MaxBidiStreams).To(Equal(params.MaxBidiStreams)) + Expect(p.IdleTimeout).To(Equal(params.IdleTimeout)) + Expect(p.DisableMigration).To(Equal(params.DisableMigration)) + Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken)) }) - Context("marshalling", func() { - It("marshals", func() { - params := &TransportParameters{ - InitialMaxStreamDataBidiLocal: 0xdeadbeef, - InitialMaxStreamDataBidiRemote: 0xbeef, - InitialMaxStreamDataUni: 0xcafe, - InitialMaxData: 0xdecafbad, - IdleTimeout: 0xcafe * time.Second, - MaxBidiStreams: 0x1234, - MaxUniStreams: 0x4321, - DisableMigration: true, - StatelessResetToken: bytes.Repeat([]byte{100}, 16), - } - b := &bytes.Buffer{} - params.marshal(b) + It("errors when the stateless_reset_token has the wrong length", func() { + params := &TransportParameters{StatelessResetToken: bytes.Repeat([]byte{100}, 15)} + b := &bytes.Buffer{} + params.marshal(b) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(MatchError("wrong length for stateless_reset_token: 15 (expected 16)")) + }) - p := &TransportParameters{} - Expect(p.unmarshal(b.Bytes())).To(Succeed()) - Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal)) - Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote)) - Expect(p.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni)) - Expect(p.InitialMaxData).To(Equal(params.InitialMaxData)) - Expect(p.MaxUniStreams).To(Equal(params.MaxUniStreams)) - Expect(p.MaxBidiStreams).To(Equal(params.MaxBidiStreams)) - Expect(p.IdleTimeout).To(Equal(params.IdleTimeout)) - Expect(p.DisableMigration).To(Equal(params.DisableMigration)) - Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken)) - }) + It("errors when the max_packet_size is too small", func() { + b := &bytes.Buffer{} + utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(1199))) + utils.WriteVarInt(b, 1199) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(MatchError("invalid value for max_packet_size: 1199 (minimum 1200)")) + }) + + It("errors when disable_migration has content", func() { + b := &bytes.Buffer{} + utils.BigEndian.WriteUint16(b, uint16(disableMigrationParameterID)) + utils.BigEndian.WriteUint16(b, 6) + b.Write([]byte("foobar")) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(MatchError("wrong length for disable_migration: 6 (expected empty)")) + }) + + It("errors when the varint value has the wrong length", func() { + b := &bytes.Buffer{} + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) + utils.BigEndian.WriteUint16(b, 2) + val := uint64(0xdeadbeef) + Expect(utils.VarIntLen(val)).ToNot(BeEquivalentTo(2)) + utils.WriteVarInt(b, val) + p := &TransportParameters{} + err := p.unmarshal(b.Bytes()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("inconsistent transport parameter length")) + }) + + It("skips unknown parameters", func() { + b := &bytes.Buffer{} + // write a known parameter + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x1337))) + utils.WriteVarInt(b, 0x1337) + // write an unknown parameter + utils.BigEndian.WriteUint16(b, 0x42) + utils.BigEndian.WriteUint16(b, 6) + b.Write([]byte("foobar")) + // write a known parameter + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiRemoteParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x42))) + utils.WriteVarInt(b, 0x42) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(Succeed()) + Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(protocol.ByteCount(0x1337))) + Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(protocol.ByteCount(0x42))) + }) + + It("rejects duplicate parameters", func() { + b := &bytes.Buffer{} + // write first parameter + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x1337))) + utils.WriteVarInt(b, 0x1337) + // write a second parameter + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiRemoteParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x42))) + utils.WriteVarInt(b, 0x42) + // write first parameter again + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x1337))) + utils.WriteVarInt(b, 0x1337) + p := &TransportParameters{} + err := p.unmarshal(b.Bytes()) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("received duplicate transport parameter")) + }) + + It("errors if there's not enough data to read", func() { + b := &bytes.Buffer{} + utils.BigEndian.WriteUint16(b, 0x42) + utils.BigEndian.WriteUint16(b, 7) + b.Write([]byte("foobar")) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(MatchError("remaining length (6) smaller than parameter length (7)")) + }) + + It("errors if there's unprocessed data after reading", func() { + b := &bytes.Buffer{} + utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(0x1337))) + utils.WriteVarInt(b, 0x1337) + b.Write([]byte("foo")) + p := &TransportParameters{} + Expect(p.unmarshal(b.Bytes())).To(MatchError("should have read all data. Still have 3 bytes")) }) }) diff --git a/internal/handshake/transport_parameters.go b/internal/handshake/transport_parameters.go index e3fea7fd..ba9e68fd 100644 --- a/internal/handshake/transport_parameters.go +++ b/internal/handshake/transport_parameters.go @@ -2,8 +2,8 @@ package handshake import ( "bytes" - "encoding/binary" "fmt" + "io" "sort" "time" @@ -35,8 +35,8 @@ type TransportParameters struct { MaxPacketSize protocol.ByteCount - MaxUniStreams uint16 - MaxBidiStreams uint16 + MaxUniStreams uint64 + MaxBidiStreams uint64 IdleTimeout time.Duration DisableMigration bool @@ -47,71 +47,45 @@ func (p *TransportParameters) unmarshal(data []byte) error { // needed to check that every parameter is only sent at most once var parameterIDs []transportParameterID - for len(data) >= 4 { - paramID := transportParameterID(binary.BigEndian.Uint16(data[:2])) - paramLen := int(binary.BigEndian.Uint16(data[2:4])) - data = data[4:] - if len(data) < paramLen { - return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", len(data), paramLen) - } + r := bytes.NewReader(data) + for r.Len() >= 4 { + paramIDInt, _ := utils.BigEndian.ReadUint16(r) + paramID := transportParameterID(paramIDInt) + paramLen, _ := utils.BigEndian.ReadUint16(r) parameterIDs = append(parameterIDs, paramID) switch paramID { - case initialMaxStreamDataBidiLocalParameterID: - if paramLen != 4 { - return fmt.Errorf("wrong length for initial_max_stream_data_bidi_local: %d (expected 4)", paramLen) + case initialMaxStreamDataBidiLocalParameterID, + initialMaxStreamDataBidiRemoteParameterID, + initialMaxStreamDataUniParameterID, + initialMaxDataParameterID, + initialMaxBidiStreamsParameterID, + initialMaxUniStreamsParameterID, + idleTimeoutParameterID, + maxPacketSizeParameterID: + if err := p.readNumericTransportParameter(r, paramID, int(paramLen)); err != nil { + return err } - p.InitialMaxStreamDataBidiLocal = protocol.ByteCount(binary.BigEndian.Uint32(data[:4])) - case initialMaxStreamDataBidiRemoteParameterID: - if paramLen != 4 { - return fmt.Errorf("wrong length for initial_max_stream_data_bidi_remote: %d (expected 4)", paramLen) + default: + if r.Len() < int(paramLen) { + return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", r.Len(), paramLen) } - p.InitialMaxStreamDataBidiRemote = protocol.ByteCount(binary.BigEndian.Uint32(data[:4])) - case initialMaxStreamDataUniParameterID: - if paramLen != 4 { - return fmt.Errorf("wrong length for initial_max_stream_data_uni: %d (expected 4)", paramLen) + switch paramID { + case disableMigrationParameterID: + if paramLen != 0 { + return fmt.Errorf("wrong length for disable_migration: %d (expected empty)", paramLen) + } + p.DisableMigration = true + case statelessResetTokenParameterID: + if paramLen != 16 { + return fmt.Errorf("wrong length for stateless_reset_token: %d (expected 16)", paramLen) + } + b := make([]byte, 16) + r.Read(b) + p.StatelessResetToken = b + default: + r.Seek(int64(paramLen), io.SeekCurrent) } - p.InitialMaxStreamDataUni = protocol.ByteCount(binary.BigEndian.Uint32(data[:4])) - case initialMaxDataParameterID: - if paramLen != 4 { - return fmt.Errorf("wrong length for initial_max_data: %d (expected 4)", paramLen) - } - p.InitialMaxData = protocol.ByteCount(binary.BigEndian.Uint32(data[:4])) - case initialMaxBidiStreamsParameterID: - if paramLen != 2 { - return fmt.Errorf("wrong length for initial_max_stream_id_bidi: %d (expected 2)", paramLen) - } - p.MaxBidiStreams = binary.BigEndian.Uint16(data[:2]) - case initialMaxUniStreamsParameterID: - if paramLen != 2 { - return fmt.Errorf("wrong length for initial_max_stream_id_uni: %d (expected 2)", paramLen) - } - p.MaxUniStreams = binary.BigEndian.Uint16(data[:2]) - case idleTimeoutParameterID: - if paramLen != 2 { - return fmt.Errorf("wrong length for idle_timeout: %d (expected 2)", paramLen) - } - p.IdleTimeout = utils.MaxDuration(protocol.MinRemoteIdleTimeout, time.Duration(binary.BigEndian.Uint16(data[:2]))*time.Second) - case maxPacketSizeParameterID: - if paramLen != 2 { - return fmt.Errorf("wrong length for max_packet_size: %d (expected 2)", paramLen) - } - maxPacketSize := protocol.ByteCount(binary.BigEndian.Uint16(data[:2])) - if maxPacketSize < 1200 { - return fmt.Errorf("invalid value for max_packet_size: %d (minimum 1200)", maxPacketSize) - } - p.MaxPacketSize = maxPacketSize - case disableMigrationParameterID: - if paramLen != 0 { - return fmt.Errorf("wrong length for disable_migration: %d (expected empty)", paramLen) - } - p.DisableMigration = true - case statelessResetTokenParameterID: - if paramLen != 16 { - return fmt.Errorf("wrong length for stateless_reset_token: %d (expected 16)", paramLen) - } - p.StatelessResetToken = data[:16] } - data = data[paramLen:] } // check that every transport parameter was sent at most once @@ -122,8 +96,47 @@ func (p *TransportParameters) unmarshal(data []byte) error { } } - if len(data) != 0 { - return fmt.Errorf("should have read all data. Still have %d bytes", len(data)) + if r.Len() != 0 { + return fmt.Errorf("should have read all data. Still have %d bytes", r.Len()) + } + return nil +} + +func (p *TransportParameters) readNumericTransportParameter( + r *bytes.Reader, + paramID transportParameterID, + expectedLen int, +) error { + remainingLen := r.Len() + val, err := utils.ReadVarInt(r) + if err != nil { + return fmt.Errorf("error while reading transport parameter %d: %s", paramID, err) + } + if remainingLen-r.Len() != expectedLen { + return fmt.Errorf("inconsistent transport parameter length for %d", paramID) + } + switch paramID { + case initialMaxStreamDataBidiLocalParameterID: + p.InitialMaxStreamDataBidiLocal = protocol.ByteCount(val) + case initialMaxStreamDataBidiRemoteParameterID: + p.InitialMaxStreamDataBidiRemote = protocol.ByteCount(val) + case initialMaxStreamDataUniParameterID: + p.InitialMaxStreamDataUni = protocol.ByteCount(val) + case initialMaxDataParameterID: + p.InitialMaxData = protocol.ByteCount(val) + case initialMaxBidiStreamsParameterID: + p.MaxBidiStreams = val + case initialMaxUniStreamsParameterID: + p.MaxUniStreams = val + case idleTimeoutParameterID: + p.IdleTimeout = utils.MaxDuration(protocol.MinRemoteIdleTimeout, time.Duration(val)*time.Second) + case maxPacketSizeParameterID: + if val < 1200 { + return fmt.Errorf("invalid value for max_packet_size: %d (minimum 1200)", val) + } + p.MaxPacketSize = protocol.ByteCount(val) + default: + return fmt.Errorf("TransportParameter BUG: transport parameter %d not found", paramID) } return nil } @@ -131,36 +144,36 @@ func (p *TransportParameters) unmarshal(data []byte) error { func (p *TransportParameters) marshal(b *bytes.Buffer) { // initial_max_stream_data_bidi_local utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) - utils.BigEndian.WriteUint16(b, 4) - utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataBidiLocal)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataBidiLocal)))) + utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataBidiLocal)) // initial_max_stream_data_bidi_remote utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiRemoteParameterID)) - utils.BigEndian.WriteUint16(b, 4) - utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataBidiRemote)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataBidiRemote)))) + utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataBidiRemote)) // initial_max_stream_data_uni utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataUniParameterID)) - utils.BigEndian.WriteUint16(b, 4) - utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataUni)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataUni)))) + utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataUni)) // initial_max_data utils.BigEndian.WriteUint16(b, uint16(initialMaxDataParameterID)) - utils.BigEndian.WriteUint16(b, 4) - utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxData)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxData)))) + utils.WriteVarInt(b, uint64(p.InitialMaxData)) // initial_max_bidi_streams utils.BigEndian.WriteUint16(b, uint16(initialMaxBidiStreamsParameterID)) - utils.BigEndian.WriteUint16(b, 2) - utils.BigEndian.WriteUint16(b, p.MaxBidiStreams) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(p.MaxBidiStreams))) + utils.WriteVarInt(b, p.MaxBidiStreams) // initial_max_uni_streams utils.BigEndian.WriteUint16(b, uint16(initialMaxUniStreamsParameterID)) - utils.BigEndian.WriteUint16(b, 2) - utils.BigEndian.WriteUint16(b, p.MaxUniStreams) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(p.MaxUniStreams))) + utils.WriteVarInt(b, p.MaxUniStreams) // idle_timeout utils.BigEndian.WriteUint16(b, uint16(idleTimeoutParameterID)) - utils.BigEndian.WriteUint16(b, 2) - utils.BigEndian.WriteUint16(b, uint16(p.IdleTimeout/time.Second)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.IdleTimeout/time.Second)))) + utils.WriteVarInt(b, uint64(p.IdleTimeout/time.Second)) // max_packet_size utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID)) - utils.BigEndian.WriteUint16(b, 2) - utils.BigEndian.WriteUint16(b, uint16(protocol.MaxReceivePacketSize)) + utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(protocol.MaxReceivePacketSize)))) + utils.WriteVarInt(b, uint64(protocol.MaxReceivePacketSize)) // disable_migration if p.DisableMigration { utils.BigEndian.WriteUint16(b, uint16(disableMigrationParameterID)) diff --git a/server.go b/server.go index 7a4eaefd..38b4a392 100644 --- a/server.go +++ b/server.go @@ -380,8 +380,8 @@ func (s *server) createNewSession( InitialMaxStreamDataUni: protocol.InitialMaxStreamData, InitialMaxData: protocol.InitialMaxData, IdleTimeout: s.config.IdleTimeout, - MaxBidiStreams: uint16(s.config.MaxIncomingStreams), - MaxUniStreams: uint16(s.config.MaxIncomingUniStreams), + MaxBidiStreams: uint64(s.config.MaxIncomingStreams), + MaxUniStreams: uint64(s.config.MaxIncomingUniStreams), DisableMigration: true, // TODO(#855): generate a real token StatelessResetToken: bytes.Repeat([]byte{42}, 16),