forked from quic-go/quic-go
implement sending of truncated ConnectionIDs
This commit is contained in:
@@ -39,7 +39,7 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
|
|||||||
h.mutex.Lock()
|
h.mutex.Lock()
|
||||||
for key, value := range params {
|
for key, value := range params {
|
||||||
switch key {
|
switch key {
|
||||||
case TagSFCW, TagCFCW, TagICSL, TagMSPC:
|
case TagSFCW, TagCFCW, TagICSL, TagMSPC, TagTCID:
|
||||||
h.params[key] = value
|
h.params[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,10 +61,10 @@ func (h *ConnectionParametersManager) GetRawValue(tag Tag) ([]byte, error) {
|
|||||||
|
|
||||||
// GetSHLOMap gets all values (except crypto values) needed for the SHLO
|
// GetSHLOMap gets all values (except crypto values) needed for the SHLO
|
||||||
func (h *ConnectionParametersManager) GetSHLOMap() map[Tag][]byte {
|
func (h *ConnectionParametersManager) GetSHLOMap() map[Tag][]byte {
|
||||||
// Since GetSHLOMap is only called from the crypto stream, and changes to
|
return map[Tag][]byte{
|
||||||
// the params are only made by the crypto stream itself, there is no data race
|
TagICSL: []byte{0x1e, 0x00, 0x00, 0x00}, //30
|
||||||
// here, and we need not copy the map.
|
TagMSPC: []byte{0x64, 0x00, 0x00, 0x00}, //100
|
||||||
return h.params
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStreamFlowControlWindow gets the size of the stream-level flow control window
|
// GetStreamFlowControlWindow gets the size of the stream-level flow control window
|
||||||
@@ -96,3 +96,23 @@ func (h *ConnectionParametersManager) GetIdleConnectionStateLifetime() time.Dura
|
|||||||
}
|
}
|
||||||
return time.Duration(binary.LittleEndian.Uint32(rawValue)) * time.Second
|
return time.Duration(binary.LittleEndian.Uint32(rawValue)) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TruncateConnectionID determines if the client requests truncated ConnectionIDs
|
||||||
|
func (h *ConnectionParametersManager) TruncateConnectionID() bool {
|
||||||
|
rawValue, err := h.GetRawValue(TagTCID)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var value uint32
|
||||||
|
buf := bytes.NewBuffer(rawValue)
|
||||||
|
err = binary.Read(buf, binary.LittleEndian, &value)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,6 +39,20 @@ var _ = Describe("ConnectionsParameterManager", func() {
|
|||||||
Expect(entryMap).To(HaveKey(TagMSPC))
|
Expect(entryMap).To(HaveKey(TagMSPC))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Context("Truncated connection IDs", func() {
|
||||||
|
It("does not send truncated connection IDs if the TCID tag is missing", func() {
|
||||||
|
Expect(cpm.TruncateConnectionID()).To(BeFalse())
|
||||||
|
})
|
||||||
|
|
||||||
|
It("reads the tag for truncated connection IDs", func() {
|
||||||
|
values := map[Tag][]byte{
|
||||||
|
TagTCID: []byte{0, 0, 0, 0},
|
||||||
|
}
|
||||||
|
cpm.SetFromMap(values)
|
||||||
|
Expect(cpm.TruncateConnectionID()).To(BeTrue())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
Context("flow control", func() {
|
Context("flow control", func() {
|
||||||
It("has the correct default flow control window", func() {
|
It("has the correct default flow control window", func() {
|
||||||
val, err := cpm.GetStreamFlowControlWindow()
|
val, err := cpm.GetStreamFlowControlWindow()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/crypto"
|
"github.com/lucas-clemente/quic-go/crypto"
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
|
"github.com/lucas-clemente/quic-go/handshake"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
"github.com/lucas-clemente/quic-go/utils"
|
"github.com/lucas-clemente/quic-go/utils"
|
||||||
)
|
)
|
||||||
@@ -20,6 +21,7 @@ type packedPacket struct {
|
|||||||
type packetPacker struct {
|
type packetPacker struct {
|
||||||
connectionID protocol.ConnectionID
|
connectionID protocol.ConnectionID
|
||||||
aead crypto.AEAD
|
aead crypto.AEAD
|
||||||
|
connectionParametersManager *handshake.ConnectionParametersManager
|
||||||
|
|
||||||
streamFrameQueue StreamFrameQueue
|
streamFrameQueue StreamFrameQueue
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, con
|
|||||||
responsePublicHeader := PublicHeader{
|
responsePublicHeader := PublicHeader{
|
||||||
ConnectionID: p.connectionID,
|
ConnectionID: p.connectionID,
|
||||||
PacketNumber: currentPacketNumber,
|
PacketNumber: currentPacketNumber,
|
||||||
|
TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
|
||||||
}
|
}
|
||||||
if err := responsePublicHeader.WritePublicHeader(&raw); err != nil {
|
if err := responsePublicHeader.WritePublicHeader(&raw); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/lucas-clemente/quic-go/crypto"
|
"github.com/lucas-clemente/quic-go/crypto"
|
||||||
"github.com/lucas-clemente/quic-go/frames"
|
"github.com/lucas-clemente/quic-go/frames"
|
||||||
|
"github.com/lucas-clemente/quic-go/handshake"
|
||||||
"github.com/lucas-clemente/quic-go/protocol"
|
"github.com/lucas-clemente/quic-go/protocol"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
@@ -17,7 +18,7 @@ var _ = Describe("Packet packer", func() {
|
|||||||
|
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
aead := &crypto.NullAEAD{}
|
aead := &crypto.NullAEAD{}
|
||||||
packer = &packetPacker{aead: aead}
|
packer = &packetPacker{aead: aead, connectionParametersManager: handshake.NewConnectionParamatersManager()}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("returns nil when no packet is queued", func() {
|
It("returns nil when no packet is queued", func() {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type PublicHeader struct {
|
|||||||
VersionFlag bool
|
VersionFlag bool
|
||||||
ResetFlag bool
|
ResetFlag bool
|
||||||
ConnectionID protocol.ConnectionID
|
ConnectionID protocol.ConnectionID
|
||||||
|
TruncateConnectionID bool
|
||||||
VersionNumber protocol.VersionNumber
|
VersionNumber protocol.VersionNumber
|
||||||
QuicVersion uint32
|
QuicVersion uint32
|
||||||
PacketNumberLen uint8
|
PacketNumberLen uint8
|
||||||
@@ -29,7 +30,7 @@ type PublicHeader struct {
|
|||||||
|
|
||||||
// WritePublicHeader writes a public header
|
// WritePublicHeader writes a public header
|
||||||
func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer) error {
|
func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer) error {
|
||||||
publicFlagByte := uint8(0x3c)
|
publicFlagByte := uint8(0x34)
|
||||||
if h.VersionFlag && h.ResetFlag {
|
if h.VersionFlag && h.ResetFlag {
|
||||||
return errResetAndVersionFlagSet
|
return errResetAndVersionFlagSet
|
||||||
}
|
}
|
||||||
@@ -39,9 +40,16 @@ func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer) error {
|
|||||||
if h.ResetFlag {
|
if h.ResetFlag {
|
||||||
publicFlagByte |= 0x02
|
publicFlagByte |= 0x02
|
||||||
}
|
}
|
||||||
|
if !h.TruncateConnectionID {
|
||||||
|
publicFlagByte |= 0x08
|
||||||
|
}
|
||||||
|
|
||||||
b.WriteByte(publicFlagByte)
|
b.WriteByte(publicFlagByte)
|
||||||
utils.WriteUint64(b, uint64(h.ConnectionID)) // TODO: Send shorter connection id if possible
|
|
||||||
|
if !h.TruncateConnectionID {
|
||||||
|
utils.WriteUint64(b, uint64(h.ConnectionID))
|
||||||
|
}
|
||||||
|
|
||||||
utils.WriteUint48(b, uint64(h.PacketNumber)) // TODO: Send shorter packet number if possible
|
utils.WriteUint48(b, uint64(h.PacketNumber)) // TODO: Send shorter packet number if possible
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,5 +125,18 @@ var _ = Describe("Public Header", func() {
|
|||||||
Expect(err).To(HaveOccurred())
|
Expect(err).To(HaveOccurred())
|
||||||
Expect(err).To(Equal(errResetAndVersionFlagSet))
|
Expect(err).To(Equal(errResetAndVersionFlagSet))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("truncates the connection ID", func() {
|
||||||
|
b := &bytes.Buffer{}
|
||||||
|
publicHeader := PublicHeader{
|
||||||
|
ConnectionID: 0x4cfa9f9b668619f6,
|
||||||
|
TruncateConnectionID: true,
|
||||||
|
}
|
||||||
|
err := publicHeader.WritePublicHeader(b)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
firstByte, _ := b.ReadByte()
|
||||||
|
Expect(firstByte & 0x08).To(BeZero())
|
||||||
|
Expect(b.Bytes()).ToNot(ContainSubstring(string([]byte{0xf6, 0x19, 0x86, 0x66, 0x9b, 0x9f, 0xfa, 0x4c})))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ func NewSession(conn connection, v protocol.VersionNumber, connectionID protocol
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
session.packer = &packetPacker{aead: cryptoSetup, connectionID: connectionID}
|
session.packer = &packetPacker{aead: cryptoSetup, connectionParametersManager: session.connectionParametersManager, connectionID: connectionID}
|
||||||
session.unpacker = &packetUnpacker{aead: cryptoSetup}
|
session.unpacker = &packetUnpacker{aead: cryptoSetup}
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ var _ = Describe("Session", func() {
|
|||||||
session.connectionParametersManager.SetFromMap(map[handshake.Tag][]byte{
|
session.connectionParametersManager.SetFromMap(map[handshake.Tag][]byte{
|
||||||
handshake.TagICSL: {0, 0, 0, 0},
|
handshake.TagICSL: {0, 0, 0, 0},
|
||||||
})
|
})
|
||||||
|
session.packer.connectionParametersManager = session.connectionParametersManager
|
||||||
session.Run() // Would normally not return
|
session.Run() // Would normally not return
|
||||||
Expect(conn.written[0]).To(ContainSubstring("No recent network activity."))
|
Expect(conn.written[0]).To(ContainSubstring("No recent network activity."))
|
||||||
close(done)
|
close(done)
|
||||||
|
|||||||
Reference in New Issue
Block a user