use varints for numeric transport parameters

This commit is contained in:
Marten Seemann 2018-11-05 12:12:58 +07:00
parent 7087a16c7f
commit 66a72a1199
5 changed files with 223 additions and 248 deletions

View file

@ -402,8 +402,8 @@ func (c *client) createNewTLSSession(version protocol.VersionNumber) error {
InitialMaxStreamDataUni: protocol.InitialMaxStreamData, InitialMaxStreamDataUni: protocol.InitialMaxStreamData,
InitialMaxData: protocol.InitialMaxData, InitialMaxData: protocol.InitialMaxData,
IdleTimeout: c.config.IdleTimeout, IdleTimeout: c.config.IdleTimeout,
MaxBidiStreams: uint16(c.config.MaxIncomingStreams), MaxBidiStreams: uint64(c.config.MaxIncomingStreams),
MaxUniStreams: uint16(c.config.MaxIncomingUniStreams), MaxUniStreams: uint64(c.config.MaxIncomingUniStreams),
DisableMigration: true, DisableMigration: true,
} }

View file

@ -185,12 +185,10 @@ type Config struct {
// MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open. // 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 not set, it will default to 100.
// If set to a negative value, it doesn't allow any bidirectional streams. // If set to a negative value, it doesn't allow any bidirectional streams.
// Values larger than 65535 (math.MaxUint16) are invalid.
MaxIncomingStreams int MaxIncomingStreams int
// MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open. // 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 not set, it will default to 100.
// If set to a negative value, it doesn't allow any unidirectional streams. // If set to a negative value, it doesn't allow any unidirectional streams.
// Values larger than 65535 (math.MaxUint16) are invalid.
MaxIncomingUniStreams int MaxIncomingUniStreams int
// KeepAlive defines whether this peer will periodically send PING frames to keep the connection alive. // KeepAlive defines whether this peer will periodically send PING frames to keep the connection alive.
KeepAlive bool KeepAlive bool

View file

@ -2,7 +2,8 @@ package handshake
import ( import (
"bytes" "bytes"
"fmt" "math"
"math/rand"
"time" "time"
"github.com/lucas-clemente/quic-go/internal/protocol" "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}")) Expect(p.String()).To(Equal("&handshake.TransportParameters{InitialMaxStreamDataBidiLocal: 0x1234, InitialMaxStreamDataBidiRemote: 0x2345, InitialMaxStreamDataUni: 0x3456, InitialMaxData: 0x4567, MaxBidiStreams: 1337, MaxUniStreams: 7331, IdleTimeout: 42s}"))
}) })
Context("parsing", func() { getRandomValue := func() uint64 {
var ( maxVals := []int64{math.MaxUint8 / 4, math.MaxUint16 / 4, math.MaxUint32 / 4, math.MaxUint64 / 4}
params *TransportParameters rand.Seed(GinkgoRandomSeed())
parameters map[transportParameterID][]byte return uint64(rand.Int63n(maxVals[int(rand.Int31n(4))]))
statelessResetToken []byte }
)
marshal := func(p map[transportParameterID][]byte) []byte { It("marshals und unmarshals", func() {
b := &bytes.Buffer{} params := &TransportParameters{
for id, val := range p { InitialMaxStreamDataBidiLocal: protocol.ByteCount(getRandomValue()),
utils.BigEndian.WriteUint16(b, uint16(id)) InitialMaxStreamDataBidiRemote: protocol.ByteCount(getRandomValue()),
utils.BigEndian.WriteUint16(b, uint16(len(val))) InitialMaxStreamDataUni: protocol.ByteCount(getRandomValue()),
b.Write(val) InitialMaxData: protocol.ByteCount(getRandomValue()),
} IdleTimeout: 0xcafe * time.Second,
return b.Bytes() MaxBidiStreams: getRandomValue(),
MaxUniStreams: getRandomValue(),
DisableMigration: true,
StatelessResetToken: bytes.Repeat([]byte{100}, 16),
} }
b := &bytes.Buffer{}
params.marshal(b)
BeforeEach(func() { p := &TransportParameters{}
params = &TransportParameters{} Expect(p.unmarshal(b.Bytes())).To(Succeed())
statelessResetToken = bytes.Repeat([]byte{42}, 16) Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal))
parameters = map[transportParameterID][]byte{ Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote))
initialMaxStreamDataBidiLocalParameterID: {0x11, 0x22, 0x33, 0x44}, Expect(p.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni))
initialMaxStreamDataBidiRemoteParameterID: {0x22, 0x33, 0x44, 0x55}, Expect(p.InitialMaxData).To(Equal(params.InitialMaxData))
initialMaxStreamDataUniParameterID: {0x33, 0x44, 0x55, 0x66}, Expect(p.MaxUniStreams).To(Equal(params.MaxUniStreams))
initialMaxDataParameterID: {0x44, 0x55, 0x66, 0x77}, Expect(p.MaxBidiStreams).To(Equal(params.MaxBidiStreams))
initialMaxBidiStreamsParameterID: {0x33, 0x44}, Expect(p.IdleTimeout).To(Equal(params.IdleTimeout))
initialMaxUniStreamsParameterID: {0x44, 0x55}, Expect(p.DisableMigration).To(Equal(params.DisableMigration))
idleTimeoutParameterID: {0x13, 0x37}, Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken))
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())
})
}) })
Context("marshalling", func() { It("errors when the stateless_reset_token has the wrong length", func() {
It("marshals", func() { params := &TransportParameters{StatelessResetToken: bytes.Repeat([]byte{100}, 15)}
params := &TransportParameters{ b := &bytes.Buffer{}
InitialMaxStreamDataBidiLocal: 0xdeadbeef, params.marshal(b)
InitialMaxStreamDataBidiRemote: 0xbeef, p := &TransportParameters{}
InitialMaxStreamDataUni: 0xcafe, Expect(p.unmarshal(b.Bytes())).To(MatchError("wrong length for stateless_reset_token: 15 (expected 16)"))
InitialMaxData: 0xdecafbad, })
IdleTimeout: 0xcafe * time.Second,
MaxBidiStreams: 0x1234,
MaxUniStreams: 0x4321,
DisableMigration: true,
StatelessResetToken: bytes.Repeat([]byte{100}, 16),
}
b := &bytes.Buffer{}
params.marshal(b)
p := &TransportParameters{} It("errors when the max_packet_size is too small", func() {
Expect(p.unmarshal(b.Bytes())).To(Succeed()) b := &bytes.Buffer{}
Expect(p.InitialMaxStreamDataBidiLocal).To(Equal(params.InitialMaxStreamDataBidiLocal)) utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID))
Expect(p.InitialMaxStreamDataBidiRemote).To(Equal(params.InitialMaxStreamDataBidiRemote)) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(1199)))
Expect(p.InitialMaxStreamDataUni).To(Equal(params.InitialMaxStreamDataUni)) utils.WriteVarInt(b, 1199)
Expect(p.InitialMaxData).To(Equal(params.InitialMaxData)) p := &TransportParameters{}
Expect(p.MaxUniStreams).To(Equal(params.MaxUniStreams)) Expect(p.unmarshal(b.Bytes())).To(MatchError("invalid value for max_packet_size: 1199 (minimum 1200)"))
Expect(p.MaxBidiStreams).To(Equal(params.MaxBidiStreams)) })
Expect(p.IdleTimeout).To(Equal(params.IdleTimeout))
Expect(p.DisableMigration).To(Equal(params.DisableMigration)) It("errors when disable_migration has content", func() {
Expect(p.StatelessResetToken).To(Equal(params.StatelessResetToken)) 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"))
}) })
}) })

View file

@ -2,8 +2,8 @@ package handshake
import ( import (
"bytes" "bytes"
"encoding/binary"
"fmt" "fmt"
"io"
"sort" "sort"
"time" "time"
@ -35,8 +35,8 @@ type TransportParameters struct {
MaxPacketSize protocol.ByteCount MaxPacketSize protocol.ByteCount
MaxUniStreams uint16 MaxUniStreams uint64
MaxBidiStreams uint16 MaxBidiStreams uint64
IdleTimeout time.Duration IdleTimeout time.Duration
DisableMigration bool 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 // needed to check that every parameter is only sent at most once
var parameterIDs []transportParameterID var parameterIDs []transportParameterID
for len(data) >= 4 { r := bytes.NewReader(data)
paramID := transportParameterID(binary.BigEndian.Uint16(data[:2])) for r.Len() >= 4 {
paramLen := int(binary.BigEndian.Uint16(data[2:4])) paramIDInt, _ := utils.BigEndian.ReadUint16(r)
data = data[4:] paramID := transportParameterID(paramIDInt)
if len(data) < paramLen { paramLen, _ := utils.BigEndian.ReadUint16(r)
return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", len(data), paramLen)
}
parameterIDs = append(parameterIDs, paramID) parameterIDs = append(parameterIDs, paramID)
switch paramID { switch paramID {
case initialMaxStreamDataBidiLocalParameterID: case initialMaxStreamDataBidiLocalParameterID,
if paramLen != 4 { initialMaxStreamDataBidiRemoteParameterID,
return fmt.Errorf("wrong length for initial_max_stream_data_bidi_local: %d (expected 4)", paramLen) 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])) default:
case initialMaxStreamDataBidiRemoteParameterID: if r.Len() < int(paramLen) {
if paramLen != 4 { return fmt.Errorf("remaining length (%d) smaller than parameter length (%d)", r.Len(), paramLen)
return fmt.Errorf("wrong length for initial_max_stream_data_bidi_remote: %d (expected 4)", paramLen)
} }
p.InitialMaxStreamDataBidiRemote = protocol.ByteCount(binary.BigEndian.Uint32(data[:4])) switch paramID {
case initialMaxStreamDataUniParameterID: case disableMigrationParameterID:
if paramLen != 4 { if paramLen != 0 {
return fmt.Errorf("wrong length for initial_max_stream_data_uni: %d (expected 4)", paramLen) 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 // 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 { if r.Len() != 0 {
return fmt.Errorf("should have read all data. Still have %d bytes", len(data)) 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 return nil
} }
@ -131,36 +144,36 @@ func (p *TransportParameters) unmarshal(data []byte) error {
func (p *TransportParameters) marshal(b *bytes.Buffer) { func (p *TransportParameters) marshal(b *bytes.Buffer) {
// initial_max_stream_data_bidi_local // initial_max_stream_data_bidi_local
utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiLocalParameterID))
utils.BigEndian.WriteUint16(b, 4) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataBidiLocal))))
utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataBidiLocal)) utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataBidiLocal))
// initial_max_stream_data_bidi_remote // initial_max_stream_data_bidi_remote
utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiRemoteParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataBidiRemoteParameterID))
utils.BigEndian.WriteUint16(b, 4) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataBidiRemote))))
utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataBidiRemote)) utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataBidiRemote))
// initial_max_stream_data_uni // initial_max_stream_data_uni
utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataUniParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxStreamDataUniParameterID))
utils.BigEndian.WriteUint16(b, 4) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxStreamDataUni))))
utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxStreamDataUni)) utils.WriteVarInt(b, uint64(p.InitialMaxStreamDataUni))
// initial_max_data // initial_max_data
utils.BigEndian.WriteUint16(b, uint16(initialMaxDataParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxDataParameterID))
utils.BigEndian.WriteUint16(b, 4) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.InitialMaxData))))
utils.BigEndian.WriteUint32(b, uint32(p.InitialMaxData)) utils.WriteVarInt(b, uint64(p.InitialMaxData))
// initial_max_bidi_streams // initial_max_bidi_streams
utils.BigEndian.WriteUint16(b, uint16(initialMaxBidiStreamsParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxBidiStreamsParameterID))
utils.BigEndian.WriteUint16(b, 2) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(p.MaxBidiStreams)))
utils.BigEndian.WriteUint16(b, p.MaxBidiStreams) utils.WriteVarInt(b, p.MaxBidiStreams)
// initial_max_uni_streams // initial_max_uni_streams
utils.BigEndian.WriteUint16(b, uint16(initialMaxUniStreamsParameterID)) utils.BigEndian.WriteUint16(b, uint16(initialMaxUniStreamsParameterID))
utils.BigEndian.WriteUint16(b, 2) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(p.MaxUniStreams)))
utils.BigEndian.WriteUint16(b, p.MaxUniStreams) utils.WriteVarInt(b, p.MaxUniStreams)
// idle_timeout // idle_timeout
utils.BigEndian.WriteUint16(b, uint16(idleTimeoutParameterID)) utils.BigEndian.WriteUint16(b, uint16(idleTimeoutParameterID))
utils.BigEndian.WriteUint16(b, 2) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(p.IdleTimeout/time.Second))))
utils.BigEndian.WriteUint16(b, uint16(p.IdleTimeout/time.Second)) utils.WriteVarInt(b, uint64(p.IdleTimeout/time.Second))
// max_packet_size // max_packet_size
utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID)) utils.BigEndian.WriteUint16(b, uint16(maxPacketSizeParameterID))
utils.BigEndian.WriteUint16(b, 2) utils.BigEndian.WriteUint16(b, uint16(utils.VarIntLen(uint64(protocol.MaxReceivePacketSize))))
utils.BigEndian.WriteUint16(b, uint16(protocol.MaxReceivePacketSize)) utils.WriteVarInt(b, uint64(protocol.MaxReceivePacketSize))
// disable_migration // disable_migration
if p.DisableMigration { if p.DisableMigration {
utils.BigEndian.WriteUint16(b, uint16(disableMigrationParameterID)) utils.BigEndian.WriteUint16(b, uint16(disableMigrationParameterID))

View file

@ -380,8 +380,8 @@ func (s *server) createNewSession(
InitialMaxStreamDataUni: protocol.InitialMaxStreamData, InitialMaxStreamDataUni: protocol.InitialMaxStreamData,
InitialMaxData: protocol.InitialMaxData, InitialMaxData: protocol.InitialMaxData,
IdleTimeout: s.config.IdleTimeout, IdleTimeout: s.config.IdleTimeout,
MaxBidiStreams: uint16(s.config.MaxIncomingStreams), MaxBidiStreams: uint64(s.config.MaxIncomingStreams),
MaxUniStreams: uint16(s.config.MaxIncomingUniStreams), MaxUniStreams: uint64(s.config.MaxIncomingUniStreams),
DisableMigration: true, DisableMigration: true,
// TODO(#855): generate a real token // TODO(#855): generate a real token
StatelessResetToken: bytes.Repeat([]byte{42}, 16), StatelessResetToken: bytes.Repeat([]byte{42}, 16),