add a timeout before crypto handshake completes

This commit is contained in:
Lucas Clemente
2016-09-08 13:37:44 +02:00
parent 634a0eb78c
commit 3b66d2f35d
2 changed files with 41 additions and 21 deletions

View File

@@ -81,6 +81,7 @@ type Session struct {
// representation, and sent back in public reset packets
largestRcvdPacketNumber protocol.PacketNumber
sessionCreationTime time.Time
lastNetworkActivityTime time.Time
timer *time.Timer
@@ -99,23 +100,29 @@ func newSession(conn connection, v protocol.VersionNumber, connectionID protocol
sentPacketHandler = ackhandler.NewSentPacketHandler()
receivedPacketHandler = ackhandler.NewReceivedPacketHandler()
now := time.Now()
session := &Session{
connectionID: connectionID,
version: v,
conn: conn,
streamCallback: streamCallback,
closeCallback: closeCallback,
conn: conn,
connectionID: connectionID,
version: v,
streamCallback: streamCallback,
closeCallback: closeCallback,
connectionParametersManager: connectionParametersManager,
sentPacketHandler: sentPacketHandler,
receivedPacketHandler: receivedPacketHandler,
flowControlManager: flowControlManager,
receivedPackets: make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets),
closeChan: make(chan *qerr.QuicError, 1),
sendingScheduled: make(chan struct{}, 1),
connectionParametersManager: connectionParametersManager,
undecryptablePackets: make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets),
aeadChanged: make(chan struct{}, 1),
timer: time.NewTimer(0),
lastNetworkActivityTime: time.Now(),
receivedPackets: make(chan *receivedPacket, protocol.MaxSessionUnprocessedPackets),
closeChan: make(chan *qerr.QuicError, 1),
sendingScheduled: make(chan struct{}, 1),
undecryptablePackets: make([]*receivedPacket, 0, protocol.MaxUndecryptablePackets),
aeadChanged: make(chan struct{}, 1),
timer: time.NewTimer(0),
lastNetworkActivityTime: now,
sessionCreationTime: now,
}
session.streamsMap = newStreamsMap(session.newStream)
@@ -196,6 +203,9 @@ func (s *Session) run() {
if time.Now().Sub(s.lastNetworkActivityTime) >= s.connectionParametersManager.GetIdleConnectionStateLifetime() {
s.Close(qerr.Error(qerr.NetworkIdleTimeout, "No recent network activity."))
}
if !s.cryptoSetup.HandshakeComplete() && time.Now().Sub(s.sessionCreationTime) >= protocol.MaxTimeForCryptoHandshake {
s.Close(qerr.Error(qerr.NetworkIdleTimeout, "Crypto handshake did not complete in time."))
}
s.garbageCollectStreams()
}
}
@@ -209,6 +219,10 @@ func (s *Session) maybeResetTimer() {
if rtoTime := s.sentPacketHandler.TimeOfFirstRTO(); !rtoTime.IsZero() {
nextDeadline = utils.MinTime(nextDeadline, rtoTime)
}
if !s.cryptoSetup.HandshakeComplete() {
handshakeDeadline := s.sessionCreationTime.Add(protocol.MaxTimeForCryptoHandshake)
nextDeadline = utils.MinTime(nextDeadline, handshakeDeadline)
}
if nextDeadline.Equal(s.currentDeadline) {
// No need to reset the timer

View File

@@ -748,15 +748,21 @@ var _ = Describe("Session", func() {
Expect(session.receivedPackets).To(Receive())
})
It("times out", func(done Done) {
session.connectionParametersManager.SetFromMap(map[handshake.Tag][]byte{
handshake.TagICSL: {0, 0, 0, 0},
Context("timeouts", func() {
It("times out due to no network activity", func(done Done) {
session.lastNetworkActivityTime = time.Now().Add(-time.Hour)
session.run() // Would normally not return
Expect(conn.written[0]).To(ContainSubstring("No recent network activity."))
close(done)
})
session.packer.connectionParametersManager = session.connectionParametersManager
session.run() // Would normally not return
Expect(conn.written[0]).To(ContainSubstring("No recent network activity."))
close(done)
}, 3)
It("times out due to non-completed crypto handshake", func(done Done) {
session.sessionCreationTime = time.Now().Add(-time.Hour)
session.run() // Would normally not return
Expect(conn.written[0]).To(ContainSubstring("Crypto handshake did not complete in time."))
close(done)
})
})
It("errors when the SentPacketHandler has too many packets tracked", func() {
streamFrame := frames.StreamFrame{StreamID: 5, Data: []byte("foobar")}