implement sending of truncated ConnectionIDs

This commit is contained in:
Marten Seemann 2016-05-06 21:53:21 +07:00
parent 965addac79
commit bb807fa5bd
8 changed files with 81 additions and 21 deletions

View file

@ -39,7 +39,7 @@ func (h *ConnectionParametersManager) SetFromMap(params map[Tag][]byte) error {
h.mutex.Lock()
for key, value := range params {
switch key {
case TagSFCW, TagCFCW, TagICSL, TagMSPC:
case TagSFCW, TagCFCW, TagICSL, TagMSPC, TagTCID:
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
func (h *ConnectionParametersManager) GetSHLOMap() map[Tag][]byte {
// Since GetSHLOMap is only called from the crypto stream, and changes to
// the params are only made by the crypto stream itself, there is no data race
// here, and we need not copy the map.
return h.params
return map[Tag][]byte{
TagICSL: []byte{0x1e, 0x00, 0x00, 0x00}, //30
TagMSPC: []byte{0x64, 0x00, 0x00, 0x00}, //100
}
}
// 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
}
// 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
}

View file

@ -39,6 +39,20 @@ var _ = Describe("ConnectionsParameterManager", func() {
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() {
It("has the correct default flow control window", func() {
val, err := cpm.GetStreamFlowControlWindow()

View file

@ -6,6 +6,7 @@ import (
"github.com/lucas-clemente/quic-go/crypto"
"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/utils"
)
@ -20,6 +21,7 @@ type packedPacket struct {
type packetPacker struct {
connectionID protocol.ConnectionID
aead crypto.AEAD
connectionParametersManager *handshake.ConnectionParametersManager
streamFrameQueue StreamFrameQueue
@ -68,6 +70,7 @@ func (p *packetPacker) PackPacket(stopWaitingFrame *frames.StopWaitingFrame, con
responsePublicHeader := PublicHeader{
ConnectionID: p.connectionID,
PacketNumber: currentPacketNumber,
TruncateConnectionID: p.connectionParametersManager.TruncateConnectionID(),
}
if err := responsePublicHeader.WritePublicHeader(&raw); err != nil {
return nil, err

View file

@ -5,6 +5,7 @@ import (
"github.com/lucas-clemente/quic-go/crypto"
"github.com/lucas-clemente/quic-go/frames"
"github.com/lucas-clemente/quic-go/handshake"
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@ -17,7 +18,7 @@ var _ = Describe("Packet packer", func() {
BeforeEach(func() {
aead := &crypto.NullAEAD{}
packer = &packetPacker{aead: aead}
packer = &packetPacker{aead: aead, connectionParametersManager: handshake.NewConnectionParamatersManager()}
})
It("returns nil when no packet is queued", func() {

View file

@ -21,6 +21,7 @@ type PublicHeader struct {
VersionFlag bool
ResetFlag bool
ConnectionID protocol.ConnectionID
TruncateConnectionID bool
VersionNumber protocol.VersionNumber
QuicVersion uint32
PacketNumberLen uint8
@ -29,7 +30,7 @@ type PublicHeader struct {
// WritePublicHeader writes a public header
func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer) error {
publicFlagByte := uint8(0x3c)
publicFlagByte := uint8(0x34)
if h.VersionFlag && h.ResetFlag {
return errResetAndVersionFlagSet
}
@ -39,9 +40,16 @@ func (h *PublicHeader) WritePublicHeader(b *bytes.Buffer) error {
if h.ResetFlag {
publicFlagByte |= 0x02
}
if !h.TruncateConnectionID {
publicFlagByte |= 0x08
}
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
return nil
}

View file

@ -125,5 +125,18 @@ var _ = Describe("Public Header", func() {
Expect(err).To(HaveOccurred())
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})))
})
})
})

View file

@ -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}
return session

View file

@ -352,6 +352,7 @@ var _ = Describe("Session", func() {
session.connectionParametersManager.SetFromMap(map[handshake.Tag][]byte{
handshake.TagICSL: {0, 0, 0, 0},
})
session.packer.connectionParametersManager = session.connectionParametersManager
session.Run() // Would normally not return
Expect(conn.written[0]).To(ContainSubstring("No recent network activity."))
close(done)