1package quic
2
3import (
4	"bytes"
5	"context"
6	"crypto/rand"
7	"crypto/tls"
8	"errors"
9	"fmt"
10	"io"
11	"net"
12	"runtime/pprof"
13	"strings"
14	"time"
15
16	"github.com/lucas-clemente/quic-go/internal/ackhandler"
17	"github.com/lucas-clemente/quic-go/internal/handshake"
18	"github.com/lucas-clemente/quic-go/internal/mocks"
19	mockackhandler "github.com/lucas-clemente/quic-go/internal/mocks/ackhandler"
20	mocklogging "github.com/lucas-clemente/quic-go/internal/mocks/logging"
21	"github.com/lucas-clemente/quic-go/internal/protocol"
22	"github.com/lucas-clemente/quic-go/internal/qerr"
23	"github.com/lucas-clemente/quic-go/internal/testutils"
24	"github.com/lucas-clemente/quic-go/internal/utils"
25	"github.com/lucas-clemente/quic-go/internal/wire"
26	"github.com/lucas-clemente/quic-go/logging"
27
28	"github.com/golang/mock/gomock"
29
30	. "github.com/onsi/ginkgo"
31	. "github.com/onsi/gomega"
32)
33
34func areSessionsRunning() bool {
35	var b bytes.Buffer
36	pprof.Lookup("goroutine").WriteTo(&b, 1)
37	return strings.Contains(b.String(), "quic-go.(*session).run")
38}
39
40func areClosedSessionsRunning() bool {
41	var b bytes.Buffer
42	pprof.Lookup("goroutine").WriteTo(&b, 1)
43	return strings.Contains(b.String(), "quic-go.(*closedLocalSession).run")
44}
45
46var _ = Describe("Session", func() {
47	var (
48		sess          *session
49		sessionRunner *MockSessionRunner
50		mconn         *MockSendConn
51		streamManager *MockStreamManager
52		packer        *MockPacker
53		cryptoSetup   *mocks.MockCryptoSetup
54		tracer        *mocklogging.MockConnectionTracer
55	)
56	remoteAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337}
57	localAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 7331}
58	srcConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
59	destConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
60	clientDestConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
61
62	getPacket := func(pn protocol.PacketNumber) *packedPacket {
63		buffer := getPacketBuffer()
64		buffer.Data = append(buffer.Data, []byte("foobar")...)
65		return &packedPacket{
66			buffer: buffer,
67			packetContents: &packetContents{
68				header: &wire.ExtendedHeader{PacketNumber: pn},
69				length: 6, // foobar
70			},
71		}
72	}
73
74	expectReplaceWithClosed := func() {
75		sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).MaxTimes(1)
76		sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
77			Expect(s).To(BeAssignableToTypeOf(&closedLocalSession{}))
78			s.shutdown()
79			Eventually(areClosedSessionsRunning).Should(BeFalse())
80		})
81	}
82
83	BeforeEach(func() {
84		Eventually(areSessionsRunning).Should(BeFalse())
85
86		sessionRunner = NewMockSessionRunner(mockCtrl)
87		mconn = NewMockSendConn(mockCtrl)
88		mconn.EXPECT().RemoteAddr().Return(remoteAddr).AnyTimes()
89		mconn.EXPECT().LocalAddr().Return(localAddr).AnyTimes()
90		tokenGenerator, err := handshake.NewTokenGenerator(rand.Reader)
91		Expect(err).ToNot(HaveOccurred())
92		tracer = mocklogging.NewMockConnectionTracer(mockCtrl)
93		tracer.EXPECT().NegotiatedVersion(gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1)
94		tracer.EXPECT().SentTransportParameters(gomock.Any())
95		tracer.EXPECT().UpdatedKeyFromTLS(gomock.Any(), gomock.Any()).AnyTimes()
96		tracer.EXPECT().UpdatedCongestionState(gomock.Any())
97		sess = newSession(
98			mconn,
99			sessionRunner,
100			nil,
101			nil,
102			clientDestConnID,
103			destConnID,
104			srcConnID,
105			protocol.StatelessResetToken{},
106			populateServerConfig(&Config{DisablePathMTUDiscovery: true}),
107			nil, // tls.Config
108			tokenGenerator,
109			false,
110			tracer,
111			1234,
112			utils.DefaultLogger,
113			protocol.VersionTLS,
114		).(*session)
115		streamManager = NewMockStreamManager(mockCtrl)
116		sess.streamsMap = streamManager
117		packer = NewMockPacker(mockCtrl)
118		sess.packer = packer
119		cryptoSetup = mocks.NewMockCryptoSetup(mockCtrl)
120		sess.cryptoStreamHandler = cryptoSetup
121		sess.handshakeComplete = true
122		sess.idleTimeout = time.Hour
123	})
124
125	AfterEach(func() {
126		Eventually(areSessionsRunning).Should(BeFalse())
127	})
128
129	Context("frame handling", func() {
130		Context("handling STREAM frames", func() {
131			It("passes STREAM frames to the stream", func() {
132				f := &wire.StreamFrame{
133					StreamID: 5,
134					Data:     []byte{0xde, 0xca, 0xfb, 0xad},
135				}
136				str := NewMockReceiveStreamI(mockCtrl)
137				str.EXPECT().handleStreamFrame(f)
138				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(str, nil)
139				Expect(sess.handleStreamFrame(f)).To(Succeed())
140			})
141
142			It("returns errors", func() {
143				testErr := errors.New("test err")
144				f := &wire.StreamFrame{
145					StreamID: 5,
146					Data:     []byte{0xde, 0xca, 0xfb, 0xad},
147				}
148				str := NewMockReceiveStreamI(mockCtrl)
149				str.EXPECT().handleStreamFrame(f).Return(testErr)
150				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(str, nil)
151				Expect(sess.handleStreamFrame(f)).To(MatchError(testErr))
152			})
153
154			It("ignores STREAM frames for closed streams", func() {
155				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(5)).Return(nil, nil) // for closed streams, the streamManager returns nil
156				Expect(sess.handleStreamFrame(&wire.StreamFrame{
157					StreamID: 5,
158					Data:     []byte("foobar"),
159				})).To(Succeed())
160			})
161		})
162
163		Context("handling ACK frames", func() {
164			It("informs the SentPacketHandler about ACKs", func() {
165				f := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 2, Largest: 3}}}
166				sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
167				sph.EXPECT().ReceivedAck(f, protocol.EncryptionHandshake, gomock.Any())
168				sess.sentPacketHandler = sph
169				err := sess.handleAckFrame(f, protocol.EncryptionHandshake)
170				Expect(err).ToNot(HaveOccurred())
171			})
172		})
173
174		Context("handling RESET_STREAM frames", func() {
175			It("closes the streams for writing", func() {
176				f := &wire.ResetStreamFrame{
177					StreamID:  555,
178					ErrorCode: 42,
179					FinalSize: 0x1337,
180				}
181				str := NewMockReceiveStreamI(mockCtrl)
182				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(555)).Return(str, nil)
183				str.EXPECT().handleResetStreamFrame(f)
184				err := sess.handleResetStreamFrame(f)
185				Expect(err).ToNot(HaveOccurred())
186			})
187
188			It("returns errors", func() {
189				f := &wire.ResetStreamFrame{
190					StreamID:  7,
191					FinalSize: 0x1337,
192				}
193				testErr := errors.New("flow control violation")
194				str := NewMockReceiveStreamI(mockCtrl)
195				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(7)).Return(str, nil)
196				str.EXPECT().handleResetStreamFrame(f).Return(testErr)
197				err := sess.handleResetStreamFrame(f)
198				Expect(err).To(MatchError(testErr))
199			})
200
201			It("ignores RESET_STREAM frames for closed streams", func() {
202				streamManager.EXPECT().GetOrOpenReceiveStream(protocol.StreamID(3)).Return(nil, nil)
203				Expect(sess.handleFrame(&wire.ResetStreamFrame{
204					StreamID:  3,
205					ErrorCode: 42,
206				}, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
207			})
208		})
209
210		Context("handling MAX_DATA and MAX_STREAM_DATA frames", func() {
211			var connFC *mocks.MockConnectionFlowController
212
213			BeforeEach(func() {
214				connFC = mocks.NewMockConnectionFlowController(mockCtrl)
215				sess.connFlowController = connFC
216			})
217
218			It("updates the flow control window of a stream", func() {
219				f := &wire.MaxStreamDataFrame{
220					StreamID:          12345,
221					MaximumStreamData: 0x1337,
222				}
223				str := NewMockSendStreamI(mockCtrl)
224				streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(12345)).Return(str, nil)
225				str.EXPECT().updateSendWindow(protocol.ByteCount(0x1337))
226				Expect(sess.handleMaxStreamDataFrame(f)).To(Succeed())
227			})
228
229			It("updates the flow control window of the connection", func() {
230				offset := protocol.ByteCount(0x800000)
231				connFC.EXPECT().UpdateSendWindow(offset)
232				sess.handleMaxDataFrame(&wire.MaxDataFrame{MaximumData: offset})
233			})
234
235			It("ignores MAX_STREAM_DATA frames for a closed stream", func() {
236				streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(10)).Return(nil, nil)
237				Expect(sess.handleFrame(&wire.MaxStreamDataFrame{
238					StreamID:          10,
239					MaximumStreamData: 1337,
240				}, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
241			})
242		})
243
244		Context("handling MAX_STREAM_ID frames", func() {
245			It("passes the frame to the streamsMap", func() {
246				f := &wire.MaxStreamsFrame{
247					Type:         protocol.StreamTypeUni,
248					MaxStreamNum: 10,
249				}
250				streamManager.EXPECT().HandleMaxStreamsFrame(f)
251				sess.handleMaxStreamsFrame(f)
252			})
253		})
254
255		Context("handling STOP_SENDING frames", func() {
256			It("passes the frame to the stream", func() {
257				f := &wire.StopSendingFrame{
258					StreamID:  5,
259					ErrorCode: 10,
260				}
261				str := NewMockSendStreamI(mockCtrl)
262				streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(5)).Return(str, nil)
263				str.EXPECT().handleStopSendingFrame(f)
264				err := sess.handleStopSendingFrame(f)
265				Expect(err).ToNot(HaveOccurred())
266			})
267
268			It("ignores STOP_SENDING frames for a closed stream", func() {
269				streamManager.EXPECT().GetOrOpenSendStream(protocol.StreamID(3)).Return(nil, nil)
270				Expect(sess.handleFrame(&wire.StopSendingFrame{
271					StreamID:  3,
272					ErrorCode: 1337,
273				}, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
274			})
275		})
276
277		It("handles NEW_CONNECTION_ID frames", func() {
278			Expect(sess.handleFrame(&wire.NewConnectionIDFrame{
279				SequenceNumber: 10,
280				ConnectionID:   protocol.ConnectionID{1, 2, 3, 4},
281			}, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
282			Expect(sess.connIDManager.queue.Back().Value.ConnectionID).To(Equal(protocol.ConnectionID{1, 2, 3, 4}))
283		})
284
285		It("handles PING frames", func() {
286			err := sess.handleFrame(&wire.PingFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{})
287			Expect(err).NotTo(HaveOccurred())
288		})
289
290		It("rejects PATH_RESPONSE frames", func() {
291			err := sess.handleFrame(&wire.PathResponseFrame{Data: [8]byte{1, 2, 3, 4, 5, 6, 7, 8}}, protocol.Encryption1RTT, protocol.ConnectionID{})
292			Expect(err).To(MatchError("unexpected PATH_RESPONSE frame"))
293		})
294
295		It("handles PATH_CHALLENGE frames", func() {
296			data := [8]byte{1, 2, 3, 4, 5, 6, 7, 8}
297			err := sess.handleFrame(&wire.PathChallengeFrame{Data: data}, protocol.Encryption1RTT, protocol.ConnectionID{})
298			Expect(err).ToNot(HaveOccurred())
299			frames, _ := sess.framer.AppendControlFrames(nil, 1000)
300			Expect(frames).To(Equal([]ackhandler.Frame{{Frame: &wire.PathResponseFrame{Data: data}}}))
301		})
302
303		It("rejects NEW_TOKEN frames", func() {
304			err := sess.handleNewTokenFrame(&wire.NewTokenFrame{})
305			Expect(err).To(HaveOccurred())
306			Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
307			Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ProtocolViolation))
308		})
309
310		It("handles BLOCKED frames", func() {
311			err := sess.handleFrame(&wire.DataBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{})
312			Expect(err).NotTo(HaveOccurred())
313		})
314
315		It("handles STREAM_BLOCKED frames", func() {
316			err := sess.handleFrame(&wire.StreamDataBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{})
317			Expect(err).NotTo(HaveOccurred())
318		})
319
320		It("handles STREAMS_BLOCKED frames", func() {
321			err := sess.handleFrame(&wire.StreamsBlockedFrame{}, protocol.Encryption1RTT, protocol.ConnectionID{})
322			Expect(err).NotTo(HaveOccurred())
323		})
324
325		It("handles CONNECTION_CLOSE frames, with a transport error code", func() {
326			expectedErr := &qerr.TransportError{
327				Remote:       true,
328				ErrorCode:    qerr.StreamLimitError,
329				ErrorMessage: "foobar",
330			}
331			streamManager.EXPECT().CloseWithError(expectedErr)
332			sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
333				Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{}))
334			})
335			sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
336				Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{}))
337			})
338			cryptoSetup.EXPECT().Close()
339			gomock.InOrder(
340				tracer.EXPECT().ClosedConnection(expectedErr),
341				tracer.EXPECT().Close(),
342			)
343
344			go func() {
345				defer GinkgoRecover()
346				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
347				Expect(sess.run()).To(MatchError(expectedErr))
348			}()
349			Expect(sess.handleFrame(&wire.ConnectionCloseFrame{
350				ErrorCode:    uint64(qerr.StreamLimitError),
351				ReasonPhrase: "foobar",
352			}, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
353			Eventually(sess.Context().Done()).Should(BeClosed())
354		})
355
356		It("handles CONNECTION_CLOSE frames, with an application error code", func() {
357			testErr := &qerr.ApplicationError{
358				Remote:       true,
359				ErrorCode:    0x1337,
360				ErrorMessage: "foobar",
361			}
362			streamManager.EXPECT().CloseWithError(testErr)
363			sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
364				Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{}))
365			})
366			sessionRunner.EXPECT().ReplaceWithClosed(clientDestConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
367				Expect(s).To(BeAssignableToTypeOf(&closedRemoteSession{}))
368			})
369			cryptoSetup.EXPECT().Close()
370			gomock.InOrder(
371				tracer.EXPECT().ClosedConnection(testErr),
372				tracer.EXPECT().Close(),
373			)
374
375			go func() {
376				defer GinkgoRecover()
377				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
378				Expect(sess.run()).To(MatchError(testErr))
379			}()
380			ccf := &wire.ConnectionCloseFrame{
381				ErrorCode:          0x1337,
382				ReasonPhrase:       "foobar",
383				IsApplicationError: true,
384			}
385			Expect(sess.handleFrame(ccf, protocol.Encryption1RTT, protocol.ConnectionID{})).To(Succeed())
386			Eventually(sess.Context().Done()).Should(BeClosed())
387		})
388
389		It("errors on HANDSHAKE_DONE frames", func() {
390			Expect(sess.handleHandshakeDoneFrame()).To(MatchError(&qerr.TransportError{
391				ErrorCode:    qerr.ProtocolViolation,
392				ErrorMessage: "received a HANDSHAKE_DONE frame",
393			}))
394		})
395	})
396
397	It("tells its versions", func() {
398		sess.version = 4242
399		Expect(sess.GetVersion()).To(Equal(protocol.VersionNumber(4242)))
400	})
401
402	Context("closing", func() {
403		var (
404			runErr         chan error
405			expectedRunErr error
406		)
407
408		BeforeEach(func() {
409			runErr = make(chan error, 1)
410			expectedRunErr = nil
411		})
412
413		AfterEach(func() {
414			if expectedRunErr != nil {
415				Eventually(runErr).Should(Receive(MatchError(expectedRunErr)))
416			} else {
417				Eventually(runErr).Should(Receive())
418			}
419		})
420
421		runSession := func() {
422			go func() {
423				defer GinkgoRecover()
424				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
425				runErr <- sess.run()
426			}()
427			Eventually(areSessionsRunning).Should(BeTrue())
428		}
429
430		It("shuts down without error", func() {
431			sess.handshakeComplete = true
432			runSession()
433			streamManager.EXPECT().CloseWithError(&qerr.ApplicationError{})
434			expectReplaceWithClosed()
435			cryptoSetup.EXPECT().Close()
436			buffer := getPacketBuffer()
437			buffer.Data = append(buffer.Data, []byte("connection close")...)
438			packer.EXPECT().PackApplicationClose(gomock.Any()).DoAndReturn(func(e *qerr.ApplicationError) (*coalescedPacket, error) {
439				Expect(e.ErrorCode).To(BeEquivalentTo(qerr.NoError))
440				Expect(e.ErrorMessage).To(BeEmpty())
441				return &coalescedPacket{buffer: buffer}, nil
442			})
443			mconn.EXPECT().Write([]byte("connection close"))
444			gomock.InOrder(
445				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
446					var appErr *ApplicationError
447					Expect(errors.As(e, &appErr)).To(BeTrue())
448					Expect(appErr.Remote).To(BeFalse())
449					Expect(appErr.ErrorCode).To(BeZero())
450				}),
451				tracer.EXPECT().Close(),
452			)
453			sess.shutdown()
454			Eventually(areSessionsRunning).Should(BeFalse())
455			Expect(sess.Context().Done()).To(BeClosed())
456		})
457
458		It("only closes once", func() {
459			runSession()
460			streamManager.EXPECT().CloseWithError(gomock.Any())
461			expectReplaceWithClosed()
462			cryptoSetup.EXPECT().Close()
463			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
464			mconn.EXPECT().Write(gomock.Any())
465			tracer.EXPECT().ClosedConnection(gomock.Any())
466			tracer.EXPECT().Close()
467			sess.shutdown()
468			sess.shutdown()
469			Eventually(areSessionsRunning).Should(BeFalse())
470			Expect(sess.Context().Done()).To(BeClosed())
471		})
472
473		It("closes with an error", func() {
474			runSession()
475			expectedErr := &qerr.ApplicationError{
476				ErrorCode:    0x1337,
477				ErrorMessage: "test error",
478			}
479			streamManager.EXPECT().CloseWithError(expectedErr)
480			expectReplaceWithClosed()
481			cryptoSetup.EXPECT().Close()
482			packer.EXPECT().PackApplicationClose(expectedErr).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
483			mconn.EXPECT().Write(gomock.Any())
484			gomock.InOrder(
485				tracer.EXPECT().ClosedConnection(expectedErr),
486				tracer.EXPECT().Close(),
487			)
488			sess.CloseWithError(0x1337, "test error")
489			Eventually(areSessionsRunning).Should(BeFalse())
490			Expect(sess.Context().Done()).To(BeClosed())
491		})
492
493		It("includes the frame type in transport-level close frames", func() {
494			runSession()
495			expectedErr := &qerr.TransportError{
496				ErrorCode:    0x1337,
497				FrameType:    0x42,
498				ErrorMessage: "test error",
499			}
500			streamManager.EXPECT().CloseWithError(expectedErr)
501			expectReplaceWithClosed()
502			cryptoSetup.EXPECT().Close()
503			packer.EXPECT().PackConnectionClose(expectedErr).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
504			mconn.EXPECT().Write(gomock.Any())
505			gomock.InOrder(
506				tracer.EXPECT().ClosedConnection(expectedErr),
507				tracer.EXPECT().Close(),
508			)
509			sess.closeLocal(expectedErr)
510			Eventually(areSessionsRunning).Should(BeFalse())
511			Expect(sess.Context().Done()).To(BeClosed())
512		})
513
514		It("destroys the session", func() {
515			runSession()
516			testErr := errors.New("close")
517			streamManager.EXPECT().CloseWithError(gomock.Any())
518			sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
519			cryptoSetup.EXPECT().Close()
520			// don't EXPECT any calls to mconn.Write()
521			gomock.InOrder(
522				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
523					var transportErr *TransportError
524					Expect(errors.As(e, &transportErr)).To(BeTrue())
525					Expect(transportErr.Remote).To(BeFalse())
526					Expect(transportErr.ErrorCode).To(Equal(qerr.InternalError))
527				}),
528				tracer.EXPECT().Close(),
529			)
530			sess.destroy(testErr)
531			Eventually(areSessionsRunning).Should(BeFalse())
532			expectedRunErr = &qerr.TransportError{
533				ErrorCode:    qerr.InternalError,
534				ErrorMessage: testErr.Error(),
535			}
536		})
537
538		It("cancels the context when the run loop exists", func() {
539			runSession()
540			streamManager.EXPECT().CloseWithError(gomock.Any())
541			expectReplaceWithClosed()
542			cryptoSetup.EXPECT().Close()
543			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
544			returned := make(chan struct{})
545			go func() {
546				defer GinkgoRecover()
547				ctx := sess.Context()
548				<-ctx.Done()
549				Expect(ctx.Err()).To(MatchError(context.Canceled))
550				close(returned)
551			}()
552			Consistently(returned).ShouldNot(BeClosed())
553			mconn.EXPECT().Write(gomock.Any())
554			tracer.EXPECT().ClosedConnection(gomock.Any())
555			tracer.EXPECT().Close()
556			sess.shutdown()
557			Eventually(returned).Should(BeClosed())
558		})
559
560		It("doesn't send any more packets after receiving a CONNECTION_CLOSE", func() {
561			unpacker := NewMockUnpacker(mockCtrl)
562			sess.handshakeConfirmed = true
563			sess.unpacker = unpacker
564			runSession()
565			cryptoSetup.EXPECT().Close()
566			streamManager.EXPECT().CloseWithError(gomock.Any())
567			sessionRunner.EXPECT().ReplaceWithClosed(gomock.Any(), gomock.Any()).AnyTimes()
568			buf := &bytes.Buffer{}
569			hdr := &wire.ExtendedHeader{
570				Header:          wire.Header{DestConnectionID: srcConnID},
571				PacketNumberLen: protocol.PacketNumberLen2,
572			}
573			Expect(hdr.Write(buf, sess.version)).To(Succeed())
574			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(*wire.Header, time.Time, []byte) (*unpackedPacket, error) {
575				buf := &bytes.Buffer{}
576				Expect((&wire.ConnectionCloseFrame{ErrorCode: uint64(qerr.StreamLimitError)}).Write(buf, sess.version)).To(Succeed())
577				return &unpackedPacket{
578					hdr:             hdr,
579					data:            buf.Bytes(),
580					encryptionLevel: protocol.Encryption1RTT,
581				}, nil
582			})
583			gomock.InOrder(
584				tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()),
585				tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()),
586				tracer.EXPECT().ClosedConnection(gomock.Any()),
587				tracer.EXPECT().Close(),
588			)
589			// don't EXPECT any calls to packer.PackPacket()
590			sess.handlePacket(&receivedPacket{
591				rcvTime:    time.Now(),
592				remoteAddr: &net.UDPAddr{},
593				buffer:     getPacketBuffer(),
594				data:       buf.Bytes(),
595			})
596			// Consistently(pack).ShouldNot(Receive())
597			Eventually(sess.Context().Done()).Should(BeClosed())
598		})
599
600		It("closes when the sendQueue encounters an error", func() {
601			sess.handshakeConfirmed = true
602			conn := NewMockSendConn(mockCtrl)
603			conn.EXPECT().Write(gomock.Any()).Return(io.ErrClosedPipe).AnyTimes()
604			sess.sendQueue = newSendQueue(conn)
605			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
606			sph.EXPECT().GetLossDetectionTimeout().Return(time.Now().Add(time.Hour)).AnyTimes()
607			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
608			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
609			// only expect a single SentPacket() call
610			sph.EXPECT().SentPacket(gomock.Any())
611			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
612			tracer.EXPECT().ClosedConnection(gomock.Any())
613			tracer.EXPECT().Close()
614			streamManager.EXPECT().CloseWithError(gomock.Any())
615			sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
616			cryptoSetup.EXPECT().Close()
617			sess.sentPacketHandler = sph
618			p := getPacket(1)
619			packer.EXPECT().PackPacket().Return(p, nil)
620			packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes()
621			runSession()
622			sess.queueControlFrame(&wire.PingFrame{})
623			sess.scheduleSending()
624			Eventually(sess.Context().Done()).Should(BeClosed())
625		})
626
627		It("closes due to a stateless reset", func() {
628			token := protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
629			runSession()
630			gomock.InOrder(
631				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
632					var srErr *StatelessResetError
633					Expect(errors.As(e, &srErr)).To(BeTrue())
634					Expect(srErr.Token).To(Equal(token))
635				}),
636				tracer.EXPECT().Close(),
637			)
638			streamManager.EXPECT().CloseWithError(gomock.Any())
639			sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
640			cryptoSetup.EXPECT().Close()
641			sess.destroy(&StatelessResetError{Token: token})
642		})
643	})
644
645	Context("receiving packets", func() {
646		var unpacker *MockUnpacker
647
648		BeforeEach(func() {
649			unpacker = NewMockUnpacker(mockCtrl)
650			sess.unpacker = unpacker
651		})
652
653		getPacket := func(extHdr *wire.ExtendedHeader, data []byte) *receivedPacket {
654			buf := &bytes.Buffer{}
655			Expect(extHdr.Write(buf, sess.version)).To(Succeed())
656			return &receivedPacket{
657				data:    append(buf.Bytes(), data...),
658				buffer:  getPacketBuffer(),
659				rcvTime: time.Now(),
660			}
661		}
662
663		It("drops Retry packets", func() {
664			p := getPacket(&wire.ExtendedHeader{Header: wire.Header{
665				IsLongHeader:     true,
666				Type:             protocol.PacketTypeRetry,
667				DestConnectionID: destConnID,
668				SrcConnectionID:  srcConnID,
669				Version:          sess.version,
670				Token:            []byte("foobar"),
671			}}, make([]byte, 16) /* Retry integrity tag */)
672			tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket)
673			Expect(sess.handlePacketImpl(p)).To(BeFalse())
674		})
675
676		It("drops Version Negotiation packets", func() {
677			b, err := wire.ComposeVersionNegotiation(srcConnID, destConnID, sess.config.Versions)
678			Expect(err).ToNot(HaveOccurred())
679			tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, protocol.ByteCount(len(b)), logging.PacketDropUnexpectedPacket)
680			Expect(sess.handlePacketImpl(&receivedPacket{
681				data:   b,
682				buffer: getPacketBuffer(),
683			})).To(BeFalse())
684		})
685
686		It("drops packets for which header decryption fails", func() {
687			p := getPacket(&wire.ExtendedHeader{
688				Header: wire.Header{
689					IsLongHeader: true,
690					Type:         protocol.PacketTypeHandshake,
691					Version:      sess.version,
692				},
693				PacketNumberLen: protocol.PacketNumberLen2,
694			}, nil)
695			p.data[0] ^= 0x40 // unset the QUIC bit
696			tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropHeaderParseError)
697			Expect(sess.handlePacketImpl(p)).To(BeFalse())
698		})
699
700		It("drops packets for which the version is unsupported", func() {
701			p := getPacket(&wire.ExtendedHeader{
702				Header: wire.Header{
703					IsLongHeader: true,
704					Type:         protocol.PacketTypeHandshake,
705					Version:      sess.version + 1,
706				},
707				PacketNumberLen: protocol.PacketNumberLen2,
708			}, nil)
709			tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, p.Size(), logging.PacketDropUnsupportedVersion)
710			Expect(sess.handlePacketImpl(p)).To(BeFalse())
711		})
712
713		It("drops packets with an unsupported version", func() {
714			origSupportedVersions := make([]protocol.VersionNumber, len(protocol.SupportedVersions))
715			copy(origSupportedVersions, protocol.SupportedVersions)
716			defer func() {
717				protocol.SupportedVersions = origSupportedVersions
718			}()
719
720			protocol.SupportedVersions = append(protocol.SupportedVersions, sess.version+1)
721			p := getPacket(&wire.ExtendedHeader{
722				Header: wire.Header{
723					IsLongHeader:     true,
724					Type:             protocol.PacketTypeHandshake,
725					DestConnectionID: destConnID,
726					SrcConnectionID:  srcConnID,
727					Version:          sess.version + 1,
728				},
729				PacketNumberLen: protocol.PacketNumberLen2,
730			}, nil)
731			tracer.EXPECT().DroppedPacket(logging.PacketTypeHandshake, p.Size(), logging.PacketDropUnexpectedVersion)
732			Expect(sess.handlePacketImpl(p)).To(BeFalse())
733		})
734
735		It("informs the ReceivedPacketHandler about non-ack-eliciting packets", func() {
736			hdr := &wire.ExtendedHeader{
737				Header:          wire.Header{DestConnectionID: srcConnID},
738				PacketNumber:    0x37,
739				PacketNumberLen: protocol.PacketNumberLen1,
740			}
741			packet := getPacket(hdr, nil)
742			packet.ecn = protocol.ECNCE
743			rcvTime := time.Now().Add(-10 * time.Second)
744			unpacker.EXPECT().Unpack(gomock.Any(), rcvTime, gomock.Any()).Return(&unpackedPacket{
745				packetNumber:    0x1337,
746				encryptionLevel: protocol.EncryptionInitial,
747				hdr:             hdr,
748				data:            []byte{0}, // one PADDING frame
749			}, nil)
750			rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl)
751			gomock.InOrder(
752				rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.EncryptionInitial),
753				rph.EXPECT().ReceivedPacket(protocol.PacketNumber(0x1337), protocol.ECNCE, protocol.EncryptionInitial, rcvTime, false),
754			)
755			sess.receivedPacketHandler = rph
756			packet.rcvTime = rcvTime
757			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
758			tracer.EXPECT().ReceivedPacket(hdr, protocol.ByteCount(len(packet.data)), []logging.Frame{})
759			Expect(sess.handlePacketImpl(packet)).To(BeTrue())
760		})
761
762		It("informs the ReceivedPacketHandler about ack-eliciting packets", func() {
763			hdr := &wire.ExtendedHeader{
764				Header:          wire.Header{DestConnectionID: srcConnID},
765				PacketNumber:    0x37,
766				PacketNumberLen: protocol.PacketNumberLen1,
767			}
768			rcvTime := time.Now().Add(-10 * time.Second)
769			buf := &bytes.Buffer{}
770			Expect((&wire.PingFrame{}).Write(buf, sess.version)).To(Succeed())
771			packet := getPacket(hdr, nil)
772			packet.ecn = protocol.ECT1
773			unpacker.EXPECT().Unpack(gomock.Any(), rcvTime, gomock.Any()).Return(&unpackedPacket{
774				packetNumber:    0x1337,
775				encryptionLevel: protocol.Encryption1RTT,
776				hdr:             hdr,
777				data:            buf.Bytes(),
778			}, nil)
779			rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl)
780			gomock.InOrder(
781				rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.Encryption1RTT),
782				rph.EXPECT().ReceivedPacket(protocol.PacketNumber(0x1337), protocol.ECT1, protocol.Encryption1RTT, rcvTime, true),
783			)
784			sess.receivedPacketHandler = rph
785			packet.rcvTime = rcvTime
786			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
787			tracer.EXPECT().ReceivedPacket(hdr, protocol.ByteCount(len(packet.data)), []logging.Frame{&logging.PingFrame{}})
788			Expect(sess.handlePacketImpl(packet)).To(BeTrue())
789		})
790
791		It("drops duplicate packets", func() {
792			hdr := &wire.ExtendedHeader{
793				Header:          wire.Header{DestConnectionID: srcConnID},
794				PacketNumber:    0x37,
795				PacketNumberLen: protocol.PacketNumberLen1,
796			}
797			packet := getPacket(hdr, nil)
798			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{
799				packetNumber:    0x1337,
800				encryptionLevel: protocol.Encryption1RTT,
801				hdr:             hdr,
802				data:            []byte("foobar"),
803			}, nil)
804			rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl)
805			rph.EXPECT().IsPotentiallyDuplicate(protocol.PacketNumber(0x1337), protocol.Encryption1RTT).Return(true)
806			sess.receivedPacketHandler = rph
807			tracer.EXPECT().DroppedPacket(logging.PacketType1RTT, protocol.ByteCount(len(packet.data)), logging.PacketDropDuplicate)
808			Expect(sess.handlePacketImpl(packet)).To(BeFalse())
809		})
810
811		It("drops a packet when unpacking fails", func() {
812			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrDecryptionFailed)
813			streamManager.EXPECT().CloseWithError(gomock.Any())
814			cryptoSetup.EXPECT().Close()
815			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
816			go func() {
817				defer GinkgoRecover()
818				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
819				sess.run()
820			}()
821			expectReplaceWithClosed()
822			p := getPacket(&wire.ExtendedHeader{
823				Header: wire.Header{
824					IsLongHeader:     true,
825					Type:             protocol.PacketTypeHandshake,
826					DestConnectionID: srcConnID,
827					Version:          sess.version,
828					Length:           2 + 6,
829				},
830				PacketNumber:    0x1337,
831				PacketNumberLen: protocol.PacketNumberLen2,
832			}, []byte("foobar"))
833			tracer.EXPECT().DroppedPacket(logging.PacketTypeHandshake, p.Size(), logging.PacketDropPayloadDecryptError)
834			sess.handlePacket(p)
835			Consistently(sess.Context().Done()).ShouldNot(BeClosed())
836			// make the go routine return
837			tracer.EXPECT().ClosedConnection(gomock.Any())
838			tracer.EXPECT().Close()
839			mconn.EXPECT().Write(gomock.Any())
840			sess.closeLocal(errors.New("close"))
841			Eventually(sess.Context().Done()).Should(BeClosed())
842		})
843
844		It("processes multiple received packets before sending one", func() {
845			sess.sessionCreationTime = time.Now()
846			var pn protocol.PacketNumber
847			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) {
848				pn++
849				return &unpackedPacket{
850					data:            []byte{0}, // PADDING frame
851					encryptionLevel: protocol.Encryption1RTT,
852					packetNumber:    pn,
853					hdr:             &wire.ExtendedHeader{Header: *hdr},
854				}, nil
855			}).Times(3)
856			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
857			tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ []logging.Frame) {
858			}).Times(3)
859			packer.EXPECT().PackCoalescedPacket() // only expect a single call
860
861			for i := 0; i < 3; i++ {
862				sess.handlePacket(getPacket(&wire.ExtendedHeader{
863					Header:          wire.Header{DestConnectionID: srcConnID},
864					PacketNumber:    0x1337,
865					PacketNumberLen: protocol.PacketNumberLen2,
866				}, []byte("foobar")))
867			}
868
869			go func() {
870				defer GinkgoRecover()
871				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
872				sess.run()
873			}()
874			Consistently(sess.Context().Done()).ShouldNot(BeClosed())
875
876			// make the go routine return
877			streamManager.EXPECT().CloseWithError(gomock.Any())
878			cryptoSetup.EXPECT().Close()
879			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
880			expectReplaceWithClosed()
881			tracer.EXPECT().ClosedConnection(gomock.Any())
882			tracer.EXPECT().Close()
883			mconn.EXPECT().Write(gomock.Any())
884			sess.closeLocal(errors.New("close"))
885			Eventually(sess.Context().Done()).Should(BeClosed())
886		})
887
888		It("doesn't processes multiple received packets before sending one before handshake completion", func() {
889			sess.handshakeComplete = false
890			sess.sessionCreationTime = time.Now()
891			var pn protocol.PacketNumber
892			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, rcvTime time.Time, data []byte) (*unpackedPacket, error) {
893				pn++
894				return &unpackedPacket{
895					data:            []byte{0}, // PADDING frame
896					encryptionLevel: protocol.Encryption1RTT,
897					packetNumber:    pn,
898					hdr:             &wire.ExtendedHeader{Header: *hdr},
899				}, nil
900			}).Times(3)
901			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
902			tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ []logging.Frame) {
903			}).Times(3)
904			packer.EXPECT().PackCoalescedPacket().Times(3) // only expect a single call
905
906			for i := 0; i < 3; i++ {
907				sess.handlePacket(getPacket(&wire.ExtendedHeader{
908					Header:          wire.Header{DestConnectionID: srcConnID},
909					PacketNumber:    0x1337,
910					PacketNumberLen: protocol.PacketNumberLen2,
911				}, []byte("foobar")))
912			}
913
914			go func() {
915				defer GinkgoRecover()
916				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
917				sess.run()
918			}()
919			Consistently(sess.Context().Done()).ShouldNot(BeClosed())
920
921			// make the go routine return
922			streamManager.EXPECT().CloseWithError(gomock.Any())
923			cryptoSetup.EXPECT().Close()
924			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
925			expectReplaceWithClosed()
926			tracer.EXPECT().ClosedConnection(gomock.Any())
927			tracer.EXPECT().Close()
928			mconn.EXPECT().Write(gomock.Any())
929			sess.closeLocal(errors.New("close"))
930			Eventually(sess.Context().Done()).Should(BeClosed())
931		})
932
933		It("closes the session when unpacking fails because the reserved bits were incorrect", func() {
934			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, wire.ErrInvalidReservedBits)
935			streamManager.EXPECT().CloseWithError(gomock.Any())
936			cryptoSetup.EXPECT().Close()
937			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
938			done := make(chan struct{})
939			go func() {
940				defer GinkgoRecover()
941				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
942				err := sess.run()
943				Expect(err).To(HaveOccurred())
944				Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
945				Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ProtocolViolation))
946				close(done)
947			}()
948			expectReplaceWithClosed()
949			mconn.EXPECT().Write(gomock.Any())
950			packet := getPacket(&wire.ExtendedHeader{
951				Header:          wire.Header{DestConnectionID: srcConnID},
952				PacketNumberLen: protocol.PacketNumberLen1,
953			}, nil)
954			tracer.EXPECT().ClosedConnection(gomock.Any())
955			tracer.EXPECT().Close()
956			sess.handlePacket(packet)
957			Eventually(sess.Context().Done()).Should(BeClosed())
958		})
959
960		It("ignores packets when unpacking the header fails", func() {
961			testErr := &headerParseError{errors.New("test error")}
962			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, testErr)
963			streamManager.EXPECT().CloseWithError(gomock.Any())
964			cryptoSetup.EXPECT().Close()
965			runErr := make(chan error)
966			go func() {
967				defer GinkgoRecover()
968				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
969				runErr <- sess.run()
970			}()
971			expectReplaceWithClosed()
972			tracer.EXPECT().DroppedPacket(logging.PacketType1RTT, gomock.Any(), logging.PacketDropHeaderParseError)
973			sess.handlePacket(getPacket(&wire.ExtendedHeader{
974				Header:          wire.Header{DestConnectionID: srcConnID},
975				PacketNumberLen: protocol.PacketNumberLen1,
976			}, nil))
977			Consistently(runErr).ShouldNot(Receive())
978			// make the go routine return
979			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
980			tracer.EXPECT().ClosedConnection(gomock.Any())
981			tracer.EXPECT().Close()
982			mconn.EXPECT().Write(gomock.Any())
983			sess.shutdown()
984			Eventually(sess.Context().Done()).Should(BeClosed())
985		})
986
987		It("closes the session when unpacking fails because of an error other than a decryption error", func() {
988			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, &qerr.TransportError{ErrorCode: qerr.ConnectionIDLimitError})
989			streamManager.EXPECT().CloseWithError(gomock.Any())
990			cryptoSetup.EXPECT().Close()
991			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
992			done := make(chan struct{})
993			go func() {
994				defer GinkgoRecover()
995				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
996				err := sess.run()
997				Expect(err).To(HaveOccurred())
998				Expect(err).To(BeAssignableToTypeOf(&qerr.TransportError{}))
999				Expect(err.(*qerr.TransportError).ErrorCode).To(Equal(qerr.ConnectionIDLimitError))
1000				close(done)
1001			}()
1002			expectReplaceWithClosed()
1003			mconn.EXPECT().Write(gomock.Any())
1004			packet := getPacket(&wire.ExtendedHeader{
1005				Header:          wire.Header{DestConnectionID: srcConnID},
1006				PacketNumberLen: protocol.PacketNumberLen1,
1007			}, nil)
1008			tracer.EXPECT().ClosedConnection(gomock.Any())
1009			tracer.EXPECT().Close()
1010			sess.handlePacket(packet)
1011			Eventually(sess.Context().Done()).Should(BeClosed())
1012		})
1013
1014		It("rejects packets with empty payload", func() {
1015			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{
1016				hdr:             &wire.ExtendedHeader{},
1017				data:            []byte{}, // no payload
1018				encryptionLevel: protocol.Encryption1RTT,
1019			}, nil)
1020			streamManager.EXPECT().CloseWithError(gomock.Any())
1021			cryptoSetup.EXPECT().Close()
1022			packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1023			done := make(chan struct{})
1024			go func() {
1025				defer GinkgoRecover()
1026				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1027				Expect(sess.run()).To(MatchError(&qerr.TransportError{
1028					ErrorCode:    qerr.ProtocolViolation,
1029					ErrorMessage: "empty packet",
1030				}))
1031				close(done)
1032			}()
1033			expectReplaceWithClosed()
1034			mconn.EXPECT().Write(gomock.Any())
1035			tracer.EXPECT().ClosedConnection(gomock.Any())
1036			tracer.EXPECT().Close()
1037			sess.handlePacket(getPacket(&wire.ExtendedHeader{
1038				Header:          wire.Header{DestConnectionID: srcConnID},
1039				PacketNumberLen: protocol.PacketNumberLen1,
1040			}, nil))
1041			Eventually(done).Should(BeClosed())
1042		})
1043
1044		It("ignores packets with a different source connection ID", func() {
1045			hdr1 := &wire.ExtendedHeader{
1046				Header: wire.Header{
1047					IsLongHeader:     true,
1048					Type:             protocol.PacketTypeInitial,
1049					DestConnectionID: destConnID,
1050					SrcConnectionID:  srcConnID,
1051					Length:           1,
1052					Version:          sess.version,
1053				},
1054				PacketNumberLen: protocol.PacketNumberLen1,
1055				PacketNumber:    1,
1056			}
1057			hdr2 := &wire.ExtendedHeader{
1058				Header: wire.Header{
1059					IsLongHeader:     true,
1060					Type:             protocol.PacketTypeInitial,
1061					DestConnectionID: destConnID,
1062					SrcConnectionID:  protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
1063					Length:           1,
1064					Version:          sess.version,
1065				},
1066				PacketNumberLen: protocol.PacketNumberLen1,
1067				PacketNumber:    2,
1068			}
1069			Expect(srcConnID).ToNot(Equal(hdr2.SrcConnectionID))
1070			// Send one packet, which might change the connection ID.
1071			// only EXPECT one call to the unpacker
1072			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{
1073				encryptionLevel: protocol.Encryption1RTT,
1074				hdr:             hdr1,
1075				data:            []byte{0}, // one PADDING frame
1076			}, nil)
1077			p1 := getPacket(hdr1, nil)
1078			tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
1079			tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(p1.data)), gomock.Any())
1080			Expect(sess.handlePacketImpl(p1)).To(BeTrue())
1081			// The next packet has to be ignored, since the source connection ID doesn't match.
1082			p2 := getPacket(hdr2, nil)
1083			tracer.EXPECT().DroppedPacket(logging.PacketTypeInitial, protocol.ByteCount(len(p2.data)), logging.PacketDropUnknownConnectionID)
1084			Expect(sess.handlePacketImpl(p2)).To(BeFalse())
1085		})
1086
1087		It("queues undecryptable packets", func() {
1088			sess.handshakeComplete = false
1089			hdr := &wire.ExtendedHeader{
1090				Header: wire.Header{
1091					IsLongHeader:     true,
1092					Type:             protocol.PacketTypeHandshake,
1093					DestConnectionID: destConnID,
1094					SrcConnectionID:  srcConnID,
1095					Length:           1,
1096					Version:          sess.version,
1097				},
1098				PacketNumberLen: protocol.PacketNumberLen1,
1099				PacketNumber:    1,
1100			}
1101			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrKeysNotYetAvailable)
1102			packet := getPacket(hdr, nil)
1103			tracer.EXPECT().BufferedPacket(logging.PacketTypeHandshake)
1104			Expect(sess.handlePacketImpl(packet)).To(BeFalse())
1105			Expect(sess.undecryptablePackets).To(Equal([]*receivedPacket{packet}))
1106		})
1107
1108		Context("updating the remote address", func() {
1109			It("doesn't support connection migration", func() {
1110				unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{
1111					encryptionLevel: protocol.Encryption1RTT,
1112					hdr:             &wire.ExtendedHeader{},
1113					data:            []byte{0}, // one PADDING frame
1114				}, nil)
1115				packet := getPacket(&wire.ExtendedHeader{
1116					Header:          wire.Header{DestConnectionID: srcConnID},
1117					PacketNumberLen: protocol.PacketNumberLen1,
1118				}, nil)
1119				packet.remoteAddr = &net.IPAddr{IP: net.IPv4(192, 168, 0, 100)}
1120				tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
1121				tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet.data)), gomock.Any())
1122				Expect(sess.handlePacketImpl(packet)).To(BeTrue())
1123			})
1124		})
1125
1126		Context("coalesced packets", func() {
1127			BeforeEach(func() {
1128				tracer.EXPECT().StartedConnection(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1)
1129			})
1130			getPacketWithLength := func(connID protocol.ConnectionID, length protocol.ByteCount) (int /* header length */, *receivedPacket) {
1131				hdr := &wire.ExtendedHeader{
1132					Header: wire.Header{
1133						IsLongHeader:     true,
1134						Type:             protocol.PacketTypeHandshake,
1135						DestConnectionID: connID,
1136						SrcConnectionID:  destConnID,
1137						Version:          protocol.VersionTLS,
1138						Length:           length,
1139					},
1140					PacketNumberLen: protocol.PacketNumberLen3,
1141				}
1142				hdrLen := hdr.GetLength(sess.version)
1143				b := make([]byte, 1)
1144				rand.Read(b)
1145				packet := getPacket(hdr, bytes.Repeat(b, int(length)-3))
1146				return int(hdrLen), packet
1147			}
1148
1149			It("cuts packets to the right length", func() {
1150				hdrLen, packet := getPacketWithLength(srcConnID, 456)
1151				unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
1152					Expect(data).To(HaveLen(hdrLen + 456 - 3))
1153					return &unpackedPacket{
1154						encryptionLevel: protocol.EncryptionHandshake,
1155						data:            []byte{0},
1156						hdr:             &wire.ExtendedHeader{},
1157					}, nil
1158				})
1159				tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet.data)), gomock.Any())
1160				Expect(sess.handlePacketImpl(packet)).To(BeTrue())
1161			})
1162
1163			It("handles coalesced packets", func() {
1164				hdrLen1, packet1 := getPacketWithLength(srcConnID, 456)
1165				unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
1166					Expect(data).To(HaveLen(hdrLen1 + 456 - 3))
1167					return &unpackedPacket{
1168						encryptionLevel: protocol.EncryptionHandshake,
1169						data:            []byte{0},
1170						packetNumber:    1,
1171						hdr:             &wire.ExtendedHeader{Header: wire.Header{SrcConnectionID: destConnID}},
1172					}, nil
1173				})
1174				hdrLen2, packet2 := getPacketWithLength(srcConnID, 123)
1175				unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
1176					Expect(data).To(HaveLen(hdrLen2 + 123 - 3))
1177					return &unpackedPacket{
1178						encryptionLevel: protocol.EncryptionHandshake,
1179						data:            []byte{0},
1180						packetNumber:    2,
1181						hdr:             &wire.ExtendedHeader{Header: wire.Header{SrcConnectionID: destConnID}},
1182					}, nil
1183				})
1184				gomock.InOrder(
1185					tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet1.data)), gomock.Any()),
1186					tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), gomock.Any()),
1187				)
1188				packet1.data = append(packet1.data, packet2.data...)
1189				Expect(sess.handlePacketImpl(packet1)).To(BeTrue())
1190			})
1191
1192			It("works with undecryptable packets", func() {
1193				sess.handshakeComplete = false
1194				hdrLen1, packet1 := getPacketWithLength(srcConnID, 456)
1195				hdrLen2, packet2 := getPacketWithLength(srcConnID, 123)
1196				gomock.InOrder(
1197					unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, handshake.ErrKeysNotYetAvailable),
1198					unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
1199						Expect(data).To(HaveLen(hdrLen2 + 123 - 3))
1200						return &unpackedPacket{
1201							encryptionLevel: protocol.EncryptionHandshake,
1202							data:            []byte{0},
1203							hdr:             &wire.ExtendedHeader{},
1204						}, nil
1205					}),
1206				)
1207				gomock.InOrder(
1208					tracer.EXPECT().BufferedPacket(gomock.Any()),
1209					tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), gomock.Any()),
1210				)
1211				packet1.data = append(packet1.data, packet2.data...)
1212				Expect(sess.handlePacketImpl(packet1)).To(BeTrue())
1213
1214				Expect(sess.undecryptablePackets).To(HaveLen(1))
1215				Expect(sess.undecryptablePackets[0].data).To(HaveLen(hdrLen1 + 456 - 3))
1216			})
1217
1218			It("ignores coalesced packet parts if the destination connection IDs don't match", func() {
1219				wrongConnID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
1220				Expect(srcConnID).ToNot(Equal(wrongConnID))
1221				hdrLen1, packet1 := getPacketWithLength(srcConnID, 456)
1222				unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(_ *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
1223					Expect(data).To(HaveLen(hdrLen1 + 456 - 3))
1224					return &unpackedPacket{
1225						encryptionLevel: protocol.EncryptionHandshake,
1226						data:            []byte{0},
1227						hdr:             &wire.ExtendedHeader{},
1228					}, nil
1229				})
1230				_, packet2 := getPacketWithLength(wrongConnID, 123)
1231				// don't EXPECT any more calls to unpacker.Unpack()
1232				gomock.InOrder(
1233					tracer.EXPECT().ReceivedPacket(gomock.Any(), protocol.ByteCount(len(packet1.data)), gomock.Any()),
1234					tracer.EXPECT().DroppedPacket(gomock.Any(), protocol.ByteCount(len(packet2.data)), logging.PacketDropUnknownConnectionID),
1235				)
1236				packet1.data = append(packet1.data, packet2.data...)
1237				Expect(sess.handlePacketImpl(packet1)).To(BeTrue())
1238			})
1239		})
1240	})
1241
1242	Context("sending packets", func() {
1243		var (
1244			sessionDone chan struct{}
1245			sender      *MockSender
1246		)
1247
1248		BeforeEach(func() {
1249			sender = NewMockSender(mockCtrl)
1250			sender.EXPECT().Run()
1251			sender.EXPECT().WouldBlock().AnyTimes()
1252			sess.sendQueue = sender
1253			sessionDone = make(chan struct{})
1254		})
1255
1256		AfterEach(func() {
1257			streamManager.EXPECT().CloseWithError(gomock.Any())
1258			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1259			expectReplaceWithClosed()
1260			cryptoSetup.EXPECT().Close()
1261			mconn.EXPECT().Write(gomock.Any())
1262			tracer.EXPECT().ClosedConnection(gomock.Any())
1263			tracer.EXPECT().Close()
1264			sender.EXPECT().Close()
1265			sess.shutdown()
1266			Eventually(sess.Context().Done()).Should(BeClosed())
1267			Eventually(sessionDone).Should(BeClosed())
1268		})
1269
1270		runSession := func() {
1271			go func() {
1272				defer GinkgoRecover()
1273				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1274				sess.run()
1275				close(sessionDone)
1276			}()
1277		}
1278
1279		It("sends packets", func() {
1280			sess.handshakeConfirmed = true
1281			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1282			sph.EXPECT().TimeUntilSend().AnyTimes()
1283			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1284			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1285			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1286			sph.EXPECT().SentPacket(gomock.Any())
1287			sess.sentPacketHandler = sph
1288			runSession()
1289			p := getPacket(1)
1290			packer.EXPECT().PackPacket().Return(p, nil)
1291			packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes()
1292			sent := make(chan struct{})
1293			sender.EXPECT().WouldBlock().AnyTimes()
1294			sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) })
1295			tracer.EXPECT().SentPacket(p.header, p.buffer.Len(), nil, []logging.Frame{})
1296			sess.scheduleSending()
1297			Eventually(sent).Should(BeClosed())
1298		})
1299
1300		It("doesn't send packets if there's nothing to send", func() {
1301			sess.handshakeConfirmed = true
1302			runSession()
1303			packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes()
1304			sess.receivedPacketHandler.ReceivedPacket(0x035e, protocol.ECNNon, protocol.Encryption1RTT, time.Now(), true)
1305			sess.scheduleSending()
1306			time.Sleep(50 * time.Millisecond) // make sure there are no calls to mconn.Write()
1307		})
1308
1309		It("sends ACK only packets", func() {
1310			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1311			sph.EXPECT().TimeUntilSend().AnyTimes()
1312			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1313			sph.EXPECT().SendMode().Return(ackhandler.SendAck)
1314			done := make(chan struct{})
1315			packer.EXPECT().MaybePackAckPacket(false).Do(func(bool) { close(done) })
1316			sess.sentPacketHandler = sph
1317			runSession()
1318			sess.scheduleSending()
1319			Eventually(done).Should(BeClosed())
1320		})
1321
1322		It("adds a BLOCKED frame when it is connection-level flow control blocked", func() {
1323			sess.handshakeConfirmed = true
1324			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1325			sph.EXPECT().TimeUntilSend().AnyTimes()
1326			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1327			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1328			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1329			sph.EXPECT().SentPacket(gomock.Any())
1330			sess.sentPacketHandler = sph
1331			fc := mocks.NewMockConnectionFlowController(mockCtrl)
1332			fc.EXPECT().IsNewlyBlocked().Return(true, protocol.ByteCount(1337))
1333			fc.EXPECT().IsNewlyBlocked()
1334			p := getPacket(1)
1335			packer.EXPECT().PackPacket().Return(p, nil)
1336			packer.EXPECT().PackPacket().Return(nil, nil).AnyTimes()
1337			sess.connFlowController = fc
1338			runSession()
1339			sent := make(chan struct{})
1340			sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) })
1341			tracer.EXPECT().SentPacket(p.header, p.length, nil, []logging.Frame{})
1342			sess.scheduleSending()
1343			Eventually(sent).Should(BeClosed())
1344			frames, _ := sess.framer.AppendControlFrames(nil, 1000)
1345			Expect(frames).To(Equal([]ackhandler.Frame{{Frame: &logging.DataBlockedFrame{MaximumData: 1337}}}))
1346		})
1347
1348		It("doesn't send when the SentPacketHandler doesn't allow it", func() {
1349			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1350			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1351			sph.EXPECT().SendMode().Return(ackhandler.SendNone).AnyTimes()
1352			sph.EXPECT().TimeUntilSend().AnyTimes()
1353			sess.sentPacketHandler = sph
1354			runSession()
1355			sess.scheduleSending()
1356			time.Sleep(50 * time.Millisecond)
1357		})
1358
1359		for _, enc := range []protocol.EncryptionLevel{protocol.EncryptionInitial, protocol.EncryptionHandshake, protocol.Encryption1RTT} {
1360			encLevel := enc
1361
1362			Context(fmt.Sprintf("sending %s probe packets", encLevel), func() {
1363				var sendMode ackhandler.SendMode
1364				var getFrame func(protocol.ByteCount) wire.Frame
1365
1366				BeforeEach(func() {
1367					//nolint:exhaustive
1368					switch encLevel {
1369					case protocol.EncryptionInitial:
1370						sendMode = ackhandler.SendPTOInitial
1371						getFrame = sess.retransmissionQueue.GetInitialFrame
1372					case protocol.EncryptionHandshake:
1373						sendMode = ackhandler.SendPTOHandshake
1374						getFrame = sess.retransmissionQueue.GetHandshakeFrame
1375					case protocol.Encryption1RTT:
1376						sendMode = ackhandler.SendPTOAppData
1377						getFrame = sess.retransmissionQueue.GetAppDataFrame
1378					}
1379				})
1380
1381				It("sends a probe packet", func() {
1382					sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1383					sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1384					sph.EXPECT().TimeUntilSend().AnyTimes()
1385					sph.EXPECT().SendMode().Return(sendMode)
1386					sph.EXPECT().SendMode().Return(ackhandler.SendNone)
1387					sph.EXPECT().QueueProbePacket(encLevel)
1388					p := getPacket(123)
1389					packer.EXPECT().MaybePackProbePacket(encLevel).Return(p, nil)
1390					sph.EXPECT().SentPacket(gomock.Any()).Do(func(packet *ackhandler.Packet) {
1391						Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(123)))
1392					})
1393					sess.sentPacketHandler = sph
1394					runSession()
1395					sent := make(chan struct{})
1396					sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) })
1397					tracer.EXPECT().SentPacket(p.header, p.length, gomock.Any(), gomock.Any())
1398					sess.scheduleSending()
1399					Eventually(sent).Should(BeClosed())
1400				})
1401
1402				It("sends a PING as a probe packet", func() {
1403					sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1404					sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1405					sph.EXPECT().TimeUntilSend().AnyTimes()
1406					sph.EXPECT().SendMode().Return(sendMode)
1407					sph.EXPECT().SendMode().Return(ackhandler.SendNone)
1408					sph.EXPECT().QueueProbePacket(encLevel).Return(false)
1409					p := getPacket(123)
1410					packer.EXPECT().MaybePackProbePacket(encLevel).Return(p, nil)
1411					sph.EXPECT().SentPacket(gomock.Any()).Do(func(packet *ackhandler.Packet) {
1412						Expect(packet.PacketNumber).To(Equal(protocol.PacketNumber(123)))
1413					})
1414					sess.sentPacketHandler = sph
1415					runSession()
1416					sent := make(chan struct{})
1417					sender.EXPECT().Send(gomock.Any()).Do(func(packet *packetBuffer) { close(sent) })
1418					tracer.EXPECT().SentPacket(p.header, p.length, gomock.Any(), gomock.Any())
1419					sess.scheduleSending()
1420					Eventually(sent).Should(BeClosed())
1421					// We're using a mock packet packer in this test.
1422					// We therefore need to test separately that the PING was actually queued.
1423					Expect(getFrame(1000)).To(BeAssignableToTypeOf(&wire.PingFrame{}))
1424				})
1425			})
1426		}
1427	})
1428
1429	Context("packet pacing", func() {
1430		var (
1431			sph    *mockackhandler.MockSentPacketHandler
1432			sender *MockSender
1433		)
1434
1435		BeforeEach(func() {
1436			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
1437			sph = mockackhandler.NewMockSentPacketHandler(mockCtrl)
1438			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1439			sess.handshakeConfirmed = true
1440			sess.handshakeComplete = true
1441			sess.sentPacketHandler = sph
1442			sender = NewMockSender(mockCtrl)
1443			sender.EXPECT().Run()
1444			sess.sendQueue = sender
1445			streamManager.EXPECT().CloseWithError(gomock.Any())
1446		})
1447
1448		AfterEach(func() {
1449			// make the go routine return
1450			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1451			expectReplaceWithClosed()
1452			cryptoSetup.EXPECT().Close()
1453			mconn.EXPECT().Write(gomock.Any())
1454			tracer.EXPECT().ClosedConnection(gomock.Any())
1455			tracer.EXPECT().Close()
1456			sender.EXPECT().Close()
1457			sess.shutdown()
1458			Eventually(sess.Context().Done()).Should(BeClosed())
1459		})
1460
1461		It("sends multiple packets one by one immediately", func() {
1462			sph.EXPECT().SentPacket(gomock.Any()).Times(2)
1463			sph.EXPECT().HasPacingBudget().Return(true).Times(2)
1464			sph.EXPECT().HasPacingBudget()
1465			sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour))
1466			sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(3)
1467			packer.EXPECT().PackPacket().Return(getPacket(10), nil)
1468			packer.EXPECT().PackPacket().Return(getPacket(11), nil)
1469			sender.EXPECT().WouldBlock().AnyTimes()
1470			sender.EXPECT().Send(gomock.Any()).Times(2)
1471			go func() {
1472				defer GinkgoRecover()
1473				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1474				sess.run()
1475			}()
1476			sess.scheduleSending()
1477			time.Sleep(50 * time.Millisecond) // make sure that only 2 packets are sent
1478		})
1479
1480		It("sends multiple packets, when the pacer allows immediate sending", func() {
1481			sph.EXPECT().SentPacket(gomock.Any())
1482			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1483			sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(2)
1484			packer.EXPECT().PackPacket().Return(getPacket(10), nil)
1485			packer.EXPECT().PackPacket().Return(nil, nil)
1486			sender.EXPECT().WouldBlock().AnyTimes()
1487			sender.EXPECT().Send(gomock.Any())
1488			go func() {
1489				defer GinkgoRecover()
1490				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1491				sess.run()
1492			}()
1493			sess.scheduleSending()
1494			time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent
1495		})
1496
1497		It("allows an ACK to be sent when pacing limited", func() {
1498			sph.EXPECT().SentPacket(gomock.Any())
1499			sph.EXPECT().HasPacingBudget()
1500			sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour))
1501			sph.EXPECT().SendMode().Return(ackhandler.SendAny)
1502			packer.EXPECT().MaybePackAckPacket(gomock.Any()).Return(getPacket(10), nil)
1503			sender.EXPECT().WouldBlock().AnyTimes()
1504			sender.EXPECT().Send(gomock.Any())
1505			go func() {
1506				defer GinkgoRecover()
1507				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1508				sess.run()
1509			}()
1510			sess.scheduleSending()
1511			time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent
1512		})
1513
1514		// when becoming congestion limited, at some point the SendMode will change from SendAny to SendAck
1515		// we shouldn't send the ACK in the same run
1516		It("doesn't send an ACK right after becoming congestion limited", func() {
1517			sph.EXPECT().SentPacket(gomock.Any())
1518			sph.EXPECT().HasPacingBudget().Return(true)
1519			sph.EXPECT().SendMode().Return(ackhandler.SendAny)
1520			sph.EXPECT().SendMode().Return(ackhandler.SendAck)
1521			packer.EXPECT().PackPacket().Return(getPacket(100), nil)
1522			sender.EXPECT().WouldBlock().AnyTimes()
1523			sender.EXPECT().Send(gomock.Any())
1524			go func() {
1525				defer GinkgoRecover()
1526				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1527				sess.run()
1528			}()
1529			sess.scheduleSending()
1530			time.Sleep(50 * time.Millisecond) // make sure that only 1 packet is sent
1531		})
1532
1533		It("paces packets", func() {
1534			pacingDelay := scaleDuration(100 * time.Millisecond)
1535			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1536			gomock.InOrder(
1537				sph.EXPECT().HasPacingBudget().Return(true),
1538				packer.EXPECT().PackPacket().Return(getPacket(100), nil),
1539				sph.EXPECT().SentPacket(gomock.Any()),
1540				sph.EXPECT().HasPacingBudget(),
1541				sph.EXPECT().TimeUntilSend().Return(time.Now().Add(pacingDelay)),
1542				sph.EXPECT().HasPacingBudget().Return(true),
1543				packer.EXPECT().PackPacket().Return(getPacket(101), nil),
1544				sph.EXPECT().SentPacket(gomock.Any()),
1545				sph.EXPECT().HasPacingBudget(),
1546				sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour)),
1547			)
1548			written := make(chan struct{}, 2)
1549			sender.EXPECT().WouldBlock().AnyTimes()
1550			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }).Times(2)
1551			go func() {
1552				defer GinkgoRecover()
1553				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1554				sess.run()
1555			}()
1556			sess.scheduleSending()
1557			Eventually(written).Should(HaveLen(1))
1558			Consistently(written, pacingDelay/2).Should(HaveLen(1))
1559			Eventually(written, 2*pacingDelay).Should(HaveLen(2))
1560		})
1561
1562		It("sends multiple packets at once", func() {
1563			sph.EXPECT().SentPacket(gomock.Any()).Times(3)
1564			sph.EXPECT().HasPacingBudget().Return(true).Times(3)
1565			sph.EXPECT().HasPacingBudget()
1566			sph.EXPECT().TimeUntilSend().Return(time.Now().Add(time.Hour))
1567			sph.EXPECT().SendMode().Return(ackhandler.SendAny).Times(4)
1568			packer.EXPECT().PackPacket().Return(getPacket(1000), nil)
1569			packer.EXPECT().PackPacket().Return(getPacket(1001), nil)
1570			packer.EXPECT().PackPacket().Return(getPacket(1002), nil)
1571			written := make(chan struct{}, 3)
1572			sender.EXPECT().WouldBlock().AnyTimes()
1573			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} }).Times(3)
1574			go func() {
1575				defer GinkgoRecover()
1576				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1577				sess.run()
1578			}()
1579			sess.scheduleSending()
1580			Eventually(written).Should(HaveLen(3))
1581		})
1582
1583		It("doesn't try to send if the send queue is full", func() {
1584			available := make(chan struct{}, 1)
1585			sender.EXPECT().WouldBlock().Return(true)
1586			sender.EXPECT().Available().Return(available)
1587			go func() {
1588				defer GinkgoRecover()
1589				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1590				sess.run()
1591			}()
1592			sess.scheduleSending()
1593			time.Sleep(scaleDuration(50 * time.Millisecond))
1594
1595			written := make(chan struct{})
1596			sender.EXPECT().WouldBlock().AnyTimes()
1597			sph.EXPECT().SentPacket(gomock.Any())
1598			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1599			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1600			packer.EXPECT().PackPacket().Return(getPacket(1000), nil)
1601			packer.EXPECT().PackPacket().Return(nil, nil)
1602			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) })
1603			available <- struct{}{}
1604			Eventually(written).Should(BeClosed())
1605		})
1606
1607		It("stops sending when there are new packets to receive", func() {
1608			sender.EXPECT().WouldBlock().AnyTimes()
1609			go func() {
1610				defer GinkgoRecover()
1611				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1612				sess.run()
1613			}()
1614
1615			written := make(chan struct{})
1616			sender.EXPECT().WouldBlock().AnyTimes()
1617			sph.EXPECT().SentPacket(gomock.Any()).Do(func(*ackhandler.Packet) {
1618				sph.EXPECT().ReceivedBytes(gomock.Any())
1619				sess.handlePacket(&receivedPacket{buffer: getPacketBuffer()})
1620			})
1621			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1622			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1623			packer.EXPECT().PackPacket().Return(getPacket(1000), nil)
1624			packer.EXPECT().PackPacket().Return(nil, nil)
1625			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { close(written) })
1626
1627			sess.scheduleSending()
1628			time.Sleep(scaleDuration(50 * time.Millisecond))
1629
1630			Eventually(written).Should(BeClosed())
1631		})
1632
1633		It("stops sending when the send queue is full", func() {
1634			sph.EXPECT().SentPacket(gomock.Any())
1635			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1636			sph.EXPECT().SendMode().Return(ackhandler.SendAny)
1637			packer.EXPECT().PackPacket().Return(getPacket(1000), nil)
1638			written := make(chan struct{}, 1)
1639			sender.EXPECT().WouldBlock()
1640			sender.EXPECT().WouldBlock().Return(true).Times(2)
1641			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} })
1642			go func() {
1643				defer GinkgoRecover()
1644				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1645				sess.run()
1646			}()
1647			available := make(chan struct{}, 1)
1648			sender.EXPECT().Available().Return(available)
1649			sess.scheduleSending()
1650			Eventually(written).Should(Receive())
1651			time.Sleep(scaleDuration(50 * time.Millisecond))
1652
1653			// now make room in the send queue
1654			sph.EXPECT().SentPacket(gomock.Any())
1655			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1656			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1657			sender.EXPECT().WouldBlock().AnyTimes()
1658			packer.EXPECT().PackPacket().Return(getPacket(1001), nil)
1659			packer.EXPECT().PackPacket().Return(nil, nil)
1660			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} })
1661			available <- struct{}{}
1662			Eventually(written).Should(Receive())
1663
1664			// The send queue is not full any more. Sending on the available channel should have no effect.
1665			available <- struct{}{}
1666			time.Sleep(scaleDuration(50 * time.Millisecond))
1667		})
1668
1669		It("doesn't set a pacing timer when there is no data to send", func() {
1670			sph.EXPECT().HasPacingBudget().Return(true)
1671			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1672			sender.EXPECT().WouldBlock().AnyTimes()
1673			packer.EXPECT().PackPacket()
1674			// don't EXPECT any calls to mconn.Write()
1675			go func() {
1676				defer GinkgoRecover()
1677				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1678				sess.run()
1679			}()
1680			sess.scheduleSending() // no packet will get sent
1681			time.Sleep(50 * time.Millisecond)
1682		})
1683
1684		It("sends a Path MTU probe packet", func() {
1685			mtuDiscoverer := NewMockMtuDiscoverer(mockCtrl)
1686			sess.mtuDiscoverer = mtuDiscoverer
1687			sess.config.DisablePathMTUDiscovery = false
1688			sph.EXPECT().SentPacket(gomock.Any())
1689			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1690			sph.EXPECT().SendMode().Return(ackhandler.SendAny)
1691			sph.EXPECT().SendMode().Return(ackhandler.SendNone)
1692			written := make(chan struct{}, 1)
1693			sender.EXPECT().WouldBlock().AnyTimes()
1694			sender.EXPECT().Send(gomock.Any()).DoAndReturn(func(p *packetBuffer) { written <- struct{}{} })
1695			gomock.InOrder(
1696				mtuDiscoverer.EXPECT().NextProbeTime(),
1697				mtuDiscoverer.EXPECT().ShouldSendProbe(gomock.Any()).Return(true),
1698				mtuDiscoverer.EXPECT().NextProbeTime(),
1699			)
1700			ping := ackhandler.Frame{Frame: &wire.PingFrame{}}
1701			mtuDiscoverer.EXPECT().GetPing().Return(ping, protocol.ByteCount(1234))
1702			packer.EXPECT().PackMTUProbePacket(ping, protocol.ByteCount(1234)).Return(getPacket(1), nil)
1703			go func() {
1704				defer GinkgoRecover()
1705				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1706				sess.run()
1707			}()
1708			sess.scheduleSending()
1709			Eventually(written).Should(Receive())
1710		})
1711	})
1712
1713	Context("scheduling sending", func() {
1714		var sender *MockSender
1715
1716		BeforeEach(func() {
1717			sender = NewMockSender(mockCtrl)
1718			sender.EXPECT().WouldBlock().AnyTimes()
1719			sender.EXPECT().Run()
1720			sess.sendQueue = sender
1721			sess.handshakeConfirmed = true
1722		})
1723
1724		AfterEach(func() {
1725			// make the go routine return
1726			expectReplaceWithClosed()
1727			streamManager.EXPECT().CloseWithError(gomock.Any())
1728			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1729			cryptoSetup.EXPECT().Close()
1730			mconn.EXPECT().Write(gomock.Any())
1731			sender.EXPECT().Close()
1732			tracer.EXPECT().ClosedConnection(gomock.Any())
1733			tracer.EXPECT().Close()
1734			sess.shutdown()
1735			Eventually(sess.Context().Done()).Should(BeClosed())
1736		})
1737
1738		It("sends when scheduleSending is called", func() {
1739			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1740			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1741			sph.EXPECT().TimeUntilSend().AnyTimes()
1742			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1743			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1744			sph.EXPECT().SentPacket(gomock.Any())
1745			sess.sentPacketHandler = sph
1746			packer.EXPECT().PackPacket().Return(getPacket(1), nil)
1747			packer.EXPECT().PackPacket().Return(nil, nil)
1748
1749			go func() {
1750				defer GinkgoRecover()
1751				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1752				sess.run()
1753			}()
1754			// don't EXPECT any calls to mconn.Write()
1755			time.Sleep(50 * time.Millisecond)
1756			// only EXPECT calls after scheduleSending is called
1757			written := make(chan struct{})
1758			sender.EXPECT().Send(gomock.Any()).Do(func(*packetBuffer) { close(written) })
1759			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
1760			sess.scheduleSending()
1761			Eventually(written).Should(BeClosed())
1762		})
1763
1764		It("sets the timer to the ack timer", func() {
1765			packer.EXPECT().PackPacket().Return(getPacket(1234), nil)
1766			packer.EXPECT().PackPacket().Return(nil, nil)
1767			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1768			sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1769			sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1770			sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1771			sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) {
1772				Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(1234)))
1773			})
1774			sess.sentPacketHandler = sph
1775			rph := mockackhandler.NewMockReceivedPacketHandler(mockCtrl)
1776			rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(10 * time.Millisecond))
1777			// make the run loop wait
1778			rph.EXPECT().GetAlarmTimeout().Return(time.Now().Add(time.Hour)).MaxTimes(1)
1779			sess.receivedPacketHandler = rph
1780
1781			written := make(chan struct{})
1782			sender.EXPECT().Send(gomock.Any()).Do(func(*packetBuffer) { close(written) })
1783			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes()
1784			go func() {
1785				defer GinkgoRecover()
1786				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1787				sess.run()
1788			}()
1789			Eventually(written).Should(BeClosed())
1790		})
1791	})
1792
1793	It("sends coalesced packets before the handshake is confirmed", func() {
1794		sess.handshakeComplete = false
1795		sess.handshakeConfirmed = false
1796		sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1797		sess.sentPacketHandler = sph
1798		buffer := getPacketBuffer()
1799		buffer.Data = append(buffer.Data, []byte("foobar")...)
1800		packer.EXPECT().PackCoalescedPacket().Return(&coalescedPacket{
1801			buffer: buffer,
1802			packets: []*packetContents{
1803				{
1804					header: &wire.ExtendedHeader{
1805						Header: wire.Header{
1806							IsLongHeader: true,
1807							Type:         protocol.PacketTypeInitial,
1808						},
1809						PacketNumber: 13,
1810					},
1811					length: 123,
1812				},
1813				{
1814					header: &wire.ExtendedHeader{
1815						Header: wire.Header{
1816							IsLongHeader: true,
1817							Type:         protocol.PacketTypeHandshake,
1818						},
1819						PacketNumber: 37,
1820					},
1821					length: 1234,
1822				},
1823			},
1824		}, nil)
1825		packer.EXPECT().PackCoalescedPacket().AnyTimes()
1826
1827		sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1828		sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1829		sph.EXPECT().TimeUntilSend().Return(time.Now()).AnyTimes()
1830		gomock.InOrder(
1831			sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) {
1832				Expect(p.EncryptionLevel).To(Equal(protocol.EncryptionInitial))
1833				Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(13)))
1834				Expect(p.Length).To(BeEquivalentTo(123))
1835			}),
1836			sph.EXPECT().SentPacket(gomock.Any()).Do(func(p *ackhandler.Packet) {
1837				Expect(p.EncryptionLevel).To(Equal(protocol.EncryptionHandshake))
1838				Expect(p.PacketNumber).To(Equal(protocol.PacketNumber(37)))
1839				Expect(p.Length).To(BeEquivalentTo(1234))
1840			}),
1841		)
1842		gomock.InOrder(
1843			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ *wire.AckFrame, _ []logging.Frame) {
1844				Expect(hdr.Type).To(Equal(protocol.PacketTypeInitial))
1845			}),
1846			tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Do(func(hdr *wire.ExtendedHeader, _ protocol.ByteCount, _ *wire.AckFrame, _ []logging.Frame) {
1847				Expect(hdr.Type).To(Equal(protocol.PacketTypeHandshake))
1848			}),
1849		)
1850
1851		sent := make(chan struct{})
1852		mconn.EXPECT().Write([]byte("foobar")).Do(func([]byte) { close(sent) })
1853
1854		go func() {
1855			defer GinkgoRecover()
1856			cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
1857			sess.run()
1858		}()
1859
1860		sess.scheduleSending()
1861		Eventually(sent).Should(BeClosed())
1862
1863		// make sure the go routine returns
1864		streamManager.EXPECT().CloseWithError(gomock.Any())
1865		expectReplaceWithClosed()
1866		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1867		cryptoSetup.EXPECT().Close()
1868		mconn.EXPECT().Write(gomock.Any())
1869		tracer.EXPECT().ClosedConnection(gomock.Any())
1870		tracer.EXPECT().Close()
1871		sess.shutdown()
1872		Eventually(sess.Context().Done()).Should(BeClosed())
1873	})
1874
1875	It("cancels the HandshakeComplete context when the handshake completes", func() {
1876		packer.EXPECT().PackCoalescedPacket().AnyTimes()
1877		finishHandshake := make(chan struct{})
1878		sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1879		sess.sentPacketHandler = sph
1880		sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1881		sph.EXPECT().TimeUntilSend().AnyTimes()
1882		sph.EXPECT().SendMode().AnyTimes()
1883		sph.EXPECT().SetHandshakeConfirmed()
1884		sessionRunner.EXPECT().Retire(clientDestConnID)
1885		go func() {
1886			defer GinkgoRecover()
1887			<-finishHandshake
1888			cryptoSetup.EXPECT().RunHandshake()
1889			cryptoSetup.EXPECT().SetHandshakeConfirmed()
1890			cryptoSetup.EXPECT().GetSessionTicket()
1891			close(sess.handshakeCompleteChan)
1892			sess.run()
1893		}()
1894		handshakeCtx := sess.HandshakeComplete()
1895		Consistently(handshakeCtx.Done()).ShouldNot(BeClosed())
1896		close(finishHandshake)
1897		Eventually(handshakeCtx.Done()).Should(BeClosed())
1898		// make sure the go routine returns
1899		streamManager.EXPECT().CloseWithError(gomock.Any())
1900		expectReplaceWithClosed()
1901		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1902		cryptoSetup.EXPECT().Close()
1903		mconn.EXPECT().Write(gomock.Any())
1904		tracer.EXPECT().ClosedConnection(gomock.Any())
1905		tracer.EXPECT().Close()
1906		sess.shutdown()
1907		Eventually(sess.Context().Done()).Should(BeClosed())
1908	})
1909
1910	It("sends a session ticket when the handshake completes", func() {
1911		const size = protocol.MaxPostHandshakeCryptoFrameSize * 3 / 2
1912		packer.EXPECT().PackCoalescedPacket().AnyTimes()
1913		finishHandshake := make(chan struct{})
1914		sessionRunner.EXPECT().Retire(clientDestConnID)
1915		go func() {
1916			defer GinkgoRecover()
1917			<-finishHandshake
1918			cryptoSetup.EXPECT().RunHandshake()
1919			cryptoSetup.EXPECT().SetHandshakeConfirmed()
1920			cryptoSetup.EXPECT().GetSessionTicket().Return(make([]byte, size), nil)
1921			close(sess.handshakeCompleteChan)
1922			sess.run()
1923		}()
1924
1925		handshakeCtx := sess.HandshakeComplete()
1926		Consistently(handshakeCtx.Done()).ShouldNot(BeClosed())
1927		close(finishHandshake)
1928		var frames []ackhandler.Frame
1929		Eventually(func() []ackhandler.Frame {
1930			frames, _ = sess.framer.AppendControlFrames(nil, protocol.MaxByteCount)
1931			return frames
1932		}).ShouldNot(BeEmpty())
1933		var count int
1934		var s int
1935		for _, f := range frames {
1936			if cf, ok := f.Frame.(*wire.CryptoFrame); ok {
1937				count++
1938				s += len(cf.Data)
1939				Expect(f.Length(sess.version)).To(BeNumerically("<=", protocol.MaxPostHandshakeCryptoFrameSize))
1940			}
1941		}
1942		Expect(size).To(BeEquivalentTo(s))
1943		// make sure the go routine returns
1944		streamManager.EXPECT().CloseWithError(gomock.Any())
1945		expectReplaceWithClosed()
1946		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1947		cryptoSetup.EXPECT().Close()
1948		mconn.EXPECT().Write(gomock.Any())
1949		tracer.EXPECT().ClosedConnection(gomock.Any())
1950		tracer.EXPECT().Close()
1951		sess.shutdown()
1952		Eventually(sess.Context().Done()).Should(BeClosed())
1953	})
1954
1955	It("doesn't cancel the HandshakeComplete context when the handshake fails", func() {
1956		packer.EXPECT().PackCoalescedPacket().AnyTimes()
1957		streamManager.EXPECT().CloseWithError(gomock.Any())
1958		expectReplaceWithClosed()
1959		packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
1960		cryptoSetup.EXPECT().Close()
1961		tracer.EXPECT().ClosedConnection(gomock.Any())
1962		tracer.EXPECT().Close()
1963		go func() {
1964			defer GinkgoRecover()
1965			cryptoSetup.EXPECT().RunHandshake()
1966			sess.run()
1967		}()
1968		handshakeCtx := sess.HandshakeComplete()
1969		Consistently(handshakeCtx.Done()).ShouldNot(BeClosed())
1970		mconn.EXPECT().Write(gomock.Any())
1971		sess.closeLocal(errors.New("handshake error"))
1972		Consistently(handshakeCtx.Done()).ShouldNot(BeClosed())
1973		Eventually(sess.Context().Done()).Should(BeClosed())
1974	})
1975
1976	It("sends a HANDSHAKE_DONE frame when the handshake completes", func() {
1977		sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
1978		sph.EXPECT().SendMode().Return(ackhandler.SendAny).AnyTimes()
1979		sph.EXPECT().GetLossDetectionTimeout().AnyTimes()
1980		sph.EXPECT().TimeUntilSend().AnyTimes()
1981		sph.EXPECT().HasPacingBudget().Return(true).AnyTimes()
1982		sph.EXPECT().SetHandshakeConfirmed()
1983		sph.EXPECT().SentPacket(gomock.Any())
1984		mconn.EXPECT().Write(gomock.Any())
1985		tracer.EXPECT().SentPacket(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any())
1986		sess.sentPacketHandler = sph
1987		done := make(chan struct{})
1988		sessionRunner.EXPECT().Retire(clientDestConnID)
1989		packer.EXPECT().PackPacket().DoAndReturn(func() (*packedPacket, error) {
1990			frames, _ := sess.framer.AppendControlFrames(nil, protocol.MaxByteCount)
1991			Expect(frames).ToNot(BeEmpty())
1992			Expect(frames[0].Frame).To(BeEquivalentTo(&wire.HandshakeDoneFrame{}))
1993			defer close(done)
1994			return &packedPacket{
1995				packetContents: &packetContents{
1996					header: &wire.ExtendedHeader{},
1997				},
1998				buffer: getPacketBuffer(),
1999			}, nil
2000		})
2001		packer.EXPECT().PackPacket().AnyTimes()
2002		go func() {
2003			defer GinkgoRecover()
2004			cryptoSetup.EXPECT().RunHandshake()
2005			cryptoSetup.EXPECT().SetHandshakeConfirmed()
2006			cryptoSetup.EXPECT().GetSessionTicket()
2007			mconn.EXPECT().Write(gomock.Any())
2008			close(sess.handshakeCompleteChan)
2009			sess.run()
2010		}()
2011		Eventually(done).Should(BeClosed())
2012		// make sure the go routine returns
2013		streamManager.EXPECT().CloseWithError(gomock.Any())
2014		expectReplaceWithClosed()
2015		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2016		cryptoSetup.EXPECT().Close()
2017		tracer.EXPECT().ClosedConnection(gomock.Any())
2018		tracer.EXPECT().Close()
2019		sess.shutdown()
2020		Eventually(sess.Context().Done()).Should(BeClosed())
2021	})
2022
2023	It("doesn't return a run error when closing", func() {
2024		done := make(chan struct{})
2025		go func() {
2026			defer GinkgoRecover()
2027			cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2028			Expect(sess.run()).To(Succeed())
2029			close(done)
2030		}()
2031		streamManager.EXPECT().CloseWithError(gomock.Any())
2032		expectReplaceWithClosed()
2033		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2034		cryptoSetup.EXPECT().Close()
2035		mconn.EXPECT().Write(gomock.Any())
2036		tracer.EXPECT().ClosedConnection(gomock.Any())
2037		tracer.EXPECT().Close()
2038		sess.shutdown()
2039		Eventually(done).Should(BeClosed())
2040	})
2041
2042	It("passes errors to the session runner", func() {
2043		testErr := errors.New("handshake error")
2044		done := make(chan struct{})
2045		go func() {
2046			defer GinkgoRecover()
2047			cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2048			err := sess.run()
2049			Expect(err).To(MatchError(&qerr.ApplicationError{
2050				ErrorCode:    0x1337,
2051				ErrorMessage: testErr.Error(),
2052			}))
2053			close(done)
2054		}()
2055		streamManager.EXPECT().CloseWithError(gomock.Any())
2056		expectReplaceWithClosed()
2057		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2058		cryptoSetup.EXPECT().Close()
2059		mconn.EXPECT().Write(gomock.Any())
2060		tracer.EXPECT().ClosedConnection(gomock.Any())
2061		tracer.EXPECT().Close()
2062		Expect(sess.CloseWithError(0x1337, testErr.Error())).To(Succeed())
2063		Eventually(done).Should(BeClosed())
2064	})
2065
2066	Context("transport parameters", func() {
2067		It("processes transport parameters received from the client", func() {
2068			params := &wire.TransportParameters{
2069				MaxIdleTimeout:                90 * time.Second,
2070				InitialMaxStreamDataBidiLocal: 0x5000,
2071				InitialMaxData:                0x5000,
2072				ActiveConnectionIDLimit:       3,
2073				// marshaling always sets it to this value
2074				MaxUDPPayloadSize:         protocol.MaxPacketBufferSize,
2075				InitialSourceConnectionID: destConnID,
2076			}
2077			streamManager.EXPECT().UpdateLimits(params)
2078			packer.EXPECT().HandleTransportParameters(params)
2079			packer.EXPECT().PackCoalescedPacket().MaxTimes(3)
2080			Expect(sess.earlySessionReady()).ToNot(BeClosed())
2081			sessionRunner.EXPECT().GetStatelessResetToken(gomock.Any()).Times(2)
2082			sessionRunner.EXPECT().Add(gomock.Any(), sess).Times(2)
2083			tracer.EXPECT().ReceivedTransportParameters(params)
2084			sess.handleTransportParameters(params)
2085			Expect(sess.earlySessionReady()).To(BeClosed())
2086		})
2087	})
2088
2089	Context("keep-alives", func() {
2090		setRemoteIdleTimeout := func(t time.Duration) {
2091			streamManager.EXPECT().UpdateLimits(gomock.Any())
2092			packer.EXPECT().HandleTransportParameters(gomock.Any())
2093			tracer.EXPECT().ReceivedTransportParameters(gomock.Any())
2094			sess.handleTransportParameters(&wire.TransportParameters{
2095				MaxIdleTimeout:            t,
2096				InitialSourceConnectionID: destConnID,
2097			})
2098		}
2099
2100		runSession := func() {
2101			go func() {
2102				defer GinkgoRecover()
2103				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2104				sess.run()
2105			}()
2106		}
2107
2108		BeforeEach(func() {
2109			sess.config.MaxIdleTimeout = 30 * time.Second
2110			sess.config.KeepAlive = true
2111			sess.receivedPacketHandler.ReceivedPacket(0, protocol.ECNNon, protocol.EncryptionHandshake, time.Now(), true)
2112		})
2113
2114		AfterEach(func() {
2115			// make the go routine return
2116			expectReplaceWithClosed()
2117			streamManager.EXPECT().CloseWithError(gomock.Any())
2118			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2119			cryptoSetup.EXPECT().Close()
2120			mconn.EXPECT().Write(gomock.Any())
2121			tracer.EXPECT().ClosedConnection(gomock.Any())
2122			tracer.EXPECT().Close()
2123			sess.shutdown()
2124			Eventually(sess.Context().Done()).Should(BeClosed())
2125		})
2126
2127		It("sends a PING as a keep-alive after half the idle timeout", func() {
2128			setRemoteIdleTimeout(5 * time.Second)
2129			sess.lastPacketReceivedTime = time.Now().Add(-5 * time.Second / 2)
2130			sent := make(chan struct{})
2131			packer.EXPECT().PackCoalescedPacket().Do(func() (*packedPacket, error) {
2132				close(sent)
2133				return nil, nil
2134			})
2135			runSession()
2136			Eventually(sent).Should(BeClosed())
2137		})
2138
2139		It("sends a PING after a maximum of protocol.MaxKeepAliveInterval", func() {
2140			sess.config.MaxIdleTimeout = time.Hour
2141			setRemoteIdleTimeout(time.Hour)
2142			sess.lastPacketReceivedTime = time.Now().Add(-protocol.MaxKeepAliveInterval).Add(-time.Millisecond)
2143			sent := make(chan struct{})
2144			packer.EXPECT().PackCoalescedPacket().Do(func() (*packedPacket, error) {
2145				close(sent)
2146				return nil, nil
2147			})
2148			runSession()
2149			Eventually(sent).Should(BeClosed())
2150		})
2151
2152		It("doesn't send a PING packet if keep-alive is disabled", func() {
2153			setRemoteIdleTimeout(5 * time.Second)
2154			sess.config.KeepAlive = false
2155			sess.lastPacketReceivedTime = time.Now().Add(-time.Second * 5 / 2)
2156			runSession()
2157			// don't EXPECT() any calls to mconn.Write()
2158			time.Sleep(50 * time.Millisecond)
2159		})
2160
2161		It("doesn't send a PING if the handshake isn't completed yet", func() {
2162			sess.config.HandshakeIdleTimeout = time.Hour
2163			sess.handshakeComplete = false
2164			// Needs to be shorter than our idle timeout.
2165			// Otherwise we'll try to send a CONNECTION_CLOSE.
2166			sess.lastPacketReceivedTime = time.Now().Add(-20 * time.Second)
2167			runSession()
2168			// don't EXPECT() any calls to mconn.Write()
2169			time.Sleep(50 * time.Millisecond)
2170		})
2171	})
2172
2173	Context("timeouts", func() {
2174		BeforeEach(func() {
2175			streamManager.EXPECT().CloseWithError(gomock.Any())
2176		})
2177
2178		It("times out due to no network activity", func() {
2179			sessionRunner.EXPECT().Remove(gomock.Any()).Times(2)
2180			sess.lastPacketReceivedTime = time.Now().Add(-time.Hour)
2181			done := make(chan struct{})
2182			cryptoSetup.EXPECT().Close()
2183			gomock.InOrder(
2184				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2185					Expect(e).To(MatchError(&qerr.IdleTimeoutError{}))
2186				}),
2187				tracer.EXPECT().Close(),
2188			)
2189			go func() {
2190				defer GinkgoRecover()
2191				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2192				err := sess.run()
2193				nerr, ok := err.(net.Error)
2194				Expect(ok).To(BeTrue())
2195				Expect(nerr.Timeout()).To(BeTrue())
2196				Expect(err).To(MatchError(qerr.ErrIdleTimeout))
2197				close(done)
2198			}()
2199			Eventually(done).Should(BeClosed())
2200		})
2201
2202		It("times out due to non-completed handshake", func() {
2203			sess.handshakeComplete = false
2204			sess.sessionCreationTime = time.Now().Add(-protocol.DefaultHandshakeTimeout).Add(-time.Second)
2205			sessionRunner.EXPECT().Remove(gomock.Any()).Times(2)
2206			cryptoSetup.EXPECT().Close()
2207			gomock.InOrder(
2208				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2209					Expect(e).To(MatchError(&HandshakeTimeoutError{}))
2210				}),
2211				tracer.EXPECT().Close(),
2212			)
2213			done := make(chan struct{})
2214			go func() {
2215				defer GinkgoRecover()
2216				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2217				err := sess.run()
2218				nerr, ok := err.(net.Error)
2219				Expect(ok).To(BeTrue())
2220				Expect(nerr.Timeout()).To(BeTrue())
2221				Expect(err).To(MatchError(qerr.ErrHandshakeTimeout))
2222				close(done)
2223			}()
2224			Eventually(done).Should(BeClosed())
2225		})
2226
2227		It("does not use the idle timeout before the handshake complete", func() {
2228			sess.handshakeComplete = false
2229			sess.config.HandshakeIdleTimeout = 9999 * time.Second
2230			sess.config.MaxIdleTimeout = 9999 * time.Second
2231			sess.lastPacketReceivedTime = time.Now().Add(-time.Minute)
2232			packer.EXPECT().PackApplicationClose(gomock.Any()).DoAndReturn(func(e *qerr.ApplicationError) (*coalescedPacket, error) {
2233				Expect(e.ErrorCode).To(BeZero())
2234				return &coalescedPacket{buffer: getPacketBuffer()}, nil
2235			})
2236			gomock.InOrder(
2237				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2238					idleTimeout := &IdleTimeoutError{}
2239					handshakeTimeout := &HandshakeTimeoutError{}
2240					Expect(errors.As(e, &idleTimeout)).To(BeFalse())
2241					Expect(errors.As(e, &handshakeTimeout)).To(BeFalse())
2242				}),
2243				tracer.EXPECT().Close(),
2244			)
2245			// the handshake timeout is irrelevant here, since it depends on the time the session was created,
2246			// and not on the last network activity
2247			go func() {
2248				defer GinkgoRecover()
2249				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2250				sess.run()
2251			}()
2252			Consistently(sess.Context().Done()).ShouldNot(BeClosed())
2253			// make the go routine return
2254			expectReplaceWithClosed()
2255			cryptoSetup.EXPECT().Close()
2256			mconn.EXPECT().Write(gomock.Any())
2257			sess.shutdown()
2258			Eventually(sess.Context().Done()).Should(BeClosed())
2259		})
2260
2261		It("closes the session due to the idle timeout before handshake", func() {
2262			sess.config.HandshakeIdleTimeout = 0
2263			packer.EXPECT().PackCoalescedPacket().AnyTimes()
2264			sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
2265			cryptoSetup.EXPECT().Close()
2266			gomock.InOrder(
2267				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2268					Expect(e).To(MatchError(&IdleTimeoutError{}))
2269				}),
2270				tracer.EXPECT().Close(),
2271			)
2272			done := make(chan struct{})
2273			sess.handshakeComplete = false
2274			go func() {
2275				defer GinkgoRecover()
2276				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2277				cryptoSetup.EXPECT().GetSessionTicket().MaxTimes(1)
2278				err := sess.run()
2279				nerr, ok := err.(net.Error)
2280				Expect(ok).To(BeTrue())
2281				Expect(nerr.Timeout()).To(BeTrue())
2282				Expect(err).To(MatchError(qerr.ErrIdleTimeout))
2283				close(done)
2284			}()
2285			Eventually(done).Should(BeClosed())
2286		})
2287
2288		It("closes the session due to the idle timeout after handshake", func() {
2289			packer.EXPECT().PackCoalescedPacket().AnyTimes()
2290			gomock.InOrder(
2291				sessionRunner.EXPECT().Retire(clientDestConnID),
2292				sessionRunner.EXPECT().Remove(gomock.Any()),
2293			)
2294			cryptoSetup.EXPECT().Close()
2295			gomock.InOrder(
2296				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2297					Expect(e).To(MatchError(&IdleTimeoutError{}))
2298				}),
2299				tracer.EXPECT().Close(),
2300			)
2301			sess.idleTimeout = 0
2302			done := make(chan struct{})
2303			go func() {
2304				defer GinkgoRecover()
2305				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2306				cryptoSetup.EXPECT().GetSessionTicket().MaxTimes(1)
2307				cryptoSetup.EXPECT().SetHandshakeConfirmed().MaxTimes(1)
2308				close(sess.handshakeCompleteChan)
2309				err := sess.run()
2310				nerr, ok := err.(net.Error)
2311				Expect(ok).To(BeTrue())
2312				Expect(nerr.Timeout()).To(BeTrue())
2313				Expect(err).To(MatchError(qerr.ErrIdleTimeout))
2314				close(done)
2315			}()
2316			Eventually(done).Should(BeClosed())
2317		})
2318
2319		It("doesn't time out when it just sent a packet", func() {
2320			sess.lastPacketReceivedTime = time.Now().Add(-time.Hour)
2321			sess.firstAckElicitingPacketAfterIdleSentTime = time.Now().Add(-time.Second)
2322			sess.idleTimeout = 30 * time.Second
2323			go func() {
2324				defer GinkgoRecover()
2325				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2326				sess.run()
2327			}()
2328			Consistently(sess.Context().Done()).ShouldNot(BeClosed())
2329			// make the go routine return
2330			packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2331			expectReplaceWithClosed()
2332			cryptoSetup.EXPECT().Close()
2333			mconn.EXPECT().Write(gomock.Any())
2334			tracer.EXPECT().ClosedConnection(gomock.Any())
2335			tracer.EXPECT().Close()
2336			sess.shutdown()
2337			Eventually(sess.Context().Done()).Should(BeClosed())
2338		})
2339	})
2340
2341	It("stores up to MaxSessionUnprocessedPackets packets", func() {
2342		done := make(chan struct{})
2343		tracer.EXPECT().DroppedPacket(logging.PacketTypeNotDetermined, logging.ByteCount(6), logging.PacketDropDOSPrevention).Do(func(logging.PacketType, logging.ByteCount, logging.PacketDropReason) {
2344			close(done)
2345		})
2346		// Nothing here should block
2347		for i := protocol.PacketNumber(0); i < protocol.MaxSessionUnprocessedPackets+1; i++ {
2348			sess.handlePacket(&receivedPacket{data: []byte("foobar")})
2349		}
2350		Eventually(done).Should(BeClosed())
2351	})
2352
2353	Context("getting streams", func() {
2354		It("opens streams", func() {
2355			mstr := NewMockStreamI(mockCtrl)
2356			streamManager.EXPECT().OpenStream().Return(mstr, nil)
2357			str, err := sess.OpenStream()
2358			Expect(err).ToNot(HaveOccurred())
2359			Expect(str).To(Equal(mstr))
2360		})
2361
2362		It("opens streams synchronously", func() {
2363			mstr := NewMockStreamI(mockCtrl)
2364			streamManager.EXPECT().OpenStreamSync(context.Background()).Return(mstr, nil)
2365			str, err := sess.OpenStreamSync(context.Background())
2366			Expect(err).ToNot(HaveOccurred())
2367			Expect(str).To(Equal(mstr))
2368		})
2369
2370		It("opens unidirectional streams", func() {
2371			mstr := NewMockSendStreamI(mockCtrl)
2372			streamManager.EXPECT().OpenUniStream().Return(mstr, nil)
2373			str, err := sess.OpenUniStream()
2374			Expect(err).ToNot(HaveOccurred())
2375			Expect(str).To(Equal(mstr))
2376		})
2377
2378		It("opens unidirectional streams synchronously", func() {
2379			mstr := NewMockSendStreamI(mockCtrl)
2380			streamManager.EXPECT().OpenUniStreamSync(context.Background()).Return(mstr, nil)
2381			str, err := sess.OpenUniStreamSync(context.Background())
2382			Expect(err).ToNot(HaveOccurred())
2383			Expect(str).To(Equal(mstr))
2384		})
2385
2386		It("accepts streams", func() {
2387			ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
2388			defer cancel()
2389			mstr := NewMockStreamI(mockCtrl)
2390			streamManager.EXPECT().AcceptStream(ctx).Return(mstr, nil)
2391			str, err := sess.AcceptStream(ctx)
2392			Expect(err).ToNot(HaveOccurred())
2393			Expect(str).To(Equal(mstr))
2394		})
2395
2396		It("accepts unidirectional streams", func() {
2397			ctx, cancel := context.WithTimeout(context.Background(), time.Second)
2398			defer cancel()
2399			mstr := NewMockReceiveStreamI(mockCtrl)
2400			streamManager.EXPECT().AcceptUniStream(ctx).Return(mstr, nil)
2401			str, err := sess.AcceptUniStream(ctx)
2402			Expect(err).ToNot(HaveOccurred())
2403			Expect(str).To(Equal(mstr))
2404		})
2405	})
2406
2407	It("returns the local address", func() {
2408		Expect(sess.LocalAddr()).To(Equal(localAddr))
2409	})
2410
2411	It("returns the remote address", func() {
2412		Expect(sess.RemoteAddr()).To(Equal(remoteAddr))
2413	})
2414})
2415
2416var _ = Describe("Client Session", func() {
2417	var (
2418		sess          *session
2419		sessionRunner *MockSessionRunner
2420		packer        *MockPacker
2421		mconn         *MockSendConn
2422		cryptoSetup   *mocks.MockCryptoSetup
2423		tracer        *mocklogging.MockConnectionTracer
2424		tlsConf       *tls.Config
2425		quicConf      *Config
2426	)
2427	srcConnID := protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8}
2428	destConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
2429
2430	getPacket := func(hdr *wire.ExtendedHeader, data []byte) *receivedPacket {
2431		buf := &bytes.Buffer{}
2432		Expect(hdr.Write(buf, sess.version)).To(Succeed())
2433		return &receivedPacket{
2434			data:   append(buf.Bytes(), data...),
2435			buffer: getPacketBuffer(),
2436		}
2437	}
2438
2439	expectReplaceWithClosed := func() {
2440		sessionRunner.EXPECT().ReplaceWithClosed(srcConnID, gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
2441			s.shutdown()
2442			Eventually(areClosedSessionsRunning).Should(BeFalse())
2443		})
2444	}
2445
2446	BeforeEach(func() {
2447		quicConf = populateClientConfig(&Config{}, true)
2448		tlsConf = nil
2449	})
2450
2451	JustBeforeEach(func() {
2452		Eventually(areSessionsRunning).Should(BeFalse())
2453
2454		mconn = NewMockSendConn(mockCtrl)
2455		mconn.EXPECT().RemoteAddr().Return(&net.UDPAddr{}).AnyTimes()
2456		mconn.EXPECT().LocalAddr().Return(&net.UDPAddr{}).AnyTimes()
2457		if tlsConf == nil {
2458			tlsConf = &tls.Config{}
2459		}
2460		sessionRunner = NewMockSessionRunner(mockCtrl)
2461		tracer = mocklogging.NewMockConnectionTracer(mockCtrl)
2462		tracer.EXPECT().NegotiatedVersion(gomock.Any(), gomock.Any(), gomock.Any()).MaxTimes(1)
2463		tracer.EXPECT().SentTransportParameters(gomock.Any())
2464		tracer.EXPECT().UpdatedKeyFromTLS(gomock.Any(), gomock.Any()).AnyTimes()
2465		tracer.EXPECT().UpdatedCongestionState(gomock.Any())
2466		sess = newClientSession(
2467			mconn,
2468			sessionRunner,
2469			destConnID,
2470			protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
2471			quicConf,
2472			tlsConf,
2473			42, // initial packet number
2474			false,
2475			false,
2476			tracer,
2477			1234,
2478			utils.DefaultLogger,
2479			protocol.VersionTLS,
2480		).(*session)
2481		packer = NewMockPacker(mockCtrl)
2482		sess.packer = packer
2483		cryptoSetup = mocks.NewMockCryptoSetup(mockCtrl)
2484		sess.cryptoStreamHandler = cryptoSetup
2485	})
2486
2487	It("changes the connection ID when receiving the first packet from the server", func() {
2488		unpacker := NewMockUnpacker(mockCtrl)
2489		unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, _ time.Time, data []byte) (*unpackedPacket, error) {
2490			return &unpackedPacket{
2491				encryptionLevel: protocol.Encryption1RTT,
2492				hdr:             &wire.ExtendedHeader{Header: *hdr},
2493				data:            []byte{0}, // one PADDING frame
2494			}, nil
2495		})
2496		sess.unpacker = unpacker
2497		go func() {
2498			defer GinkgoRecover()
2499			cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2500			sess.run()
2501		}()
2502		newConnID := protocol.ConnectionID{1, 3, 3, 7, 1, 3, 3, 7}
2503		p := getPacket(&wire.ExtendedHeader{
2504			Header: wire.Header{
2505				IsLongHeader:     true,
2506				Type:             protocol.PacketTypeHandshake,
2507				SrcConnectionID:  newConnID,
2508				DestConnectionID: srcConnID,
2509				Length:           2 + 6,
2510				Version:          sess.version,
2511			},
2512			PacketNumberLen: protocol.PacketNumberLen2,
2513		}, []byte("foobar"))
2514		tracer.EXPECT().ReceivedPacket(gomock.Any(), p.Size(), []logging.Frame{})
2515		Expect(sess.handlePacketImpl(p)).To(BeTrue())
2516		// make sure the go routine returns
2517		packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil)
2518		expectReplaceWithClosed()
2519		cryptoSetup.EXPECT().Close()
2520		mconn.EXPECT().Write(gomock.Any())
2521		tracer.EXPECT().ClosedConnection(gomock.Any())
2522		tracer.EXPECT().Close()
2523		sess.shutdown()
2524		Eventually(sess.Context().Done()).Should(BeClosed())
2525	})
2526
2527	It("continues accepting Long Header packets after using a new connection ID", func() {
2528		unpacker := NewMockUnpacker(mockCtrl)
2529		sess.unpacker = unpacker
2530		sessionRunner.EXPECT().AddResetToken(gomock.Any(), gomock.Any())
2531		sess.connIDManager.SetHandshakeComplete()
2532		sess.handleNewConnectionIDFrame(&wire.NewConnectionIDFrame{
2533			SequenceNumber: 1,
2534			ConnectionID:   protocol.ConnectionID{1, 2, 3, 4, 5},
2535		})
2536		Expect(sess.connIDManager.Get()).To(Equal(protocol.ConnectionID{1, 2, 3, 4, 5}))
2537		// now receive a packet with the original source connection ID
2538		unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).DoAndReturn(func(hdr *wire.Header, _ time.Time, _ []byte) (*unpackedPacket, error) {
2539			return &unpackedPacket{
2540				hdr:             &wire.ExtendedHeader{Header: *hdr},
2541				data:            []byte{0},
2542				encryptionLevel: protocol.EncryptionHandshake,
2543			}, nil
2544		})
2545		hdr := &wire.Header{
2546			IsLongHeader:     true,
2547			Type:             protocol.PacketTypeHandshake,
2548			DestConnectionID: srcConnID,
2549			SrcConnectionID:  destConnID,
2550		}
2551		tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any())
2552		Expect(sess.handleSinglePacket(&receivedPacket{buffer: getPacketBuffer()}, hdr)).To(BeTrue())
2553	})
2554
2555	It("handles HANDSHAKE_DONE frames", func() {
2556		sess.peerParams = &wire.TransportParameters{}
2557		sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
2558		sess.sentPacketHandler = sph
2559		sph.EXPECT().SetHandshakeConfirmed()
2560		cryptoSetup.EXPECT().SetHandshakeConfirmed()
2561		Expect(sess.handleHandshakeDoneFrame()).To(Succeed())
2562	})
2563
2564	It("interprets an ACK for 1-RTT packets as confirmation of the handshake", func() {
2565		sess.peerParams = &wire.TransportParameters{}
2566		sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
2567		sess.sentPacketHandler = sph
2568		ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 1, Largest: 3}}}
2569		sph.EXPECT().ReceivedAck(ack, protocol.Encryption1RTT, gomock.Any()).Return(true, nil)
2570		sph.EXPECT().SetHandshakeConfirmed()
2571		cryptoSetup.EXPECT().SetLargest1RTTAcked(protocol.PacketNumber(3))
2572		cryptoSetup.EXPECT().SetHandshakeConfirmed()
2573		Expect(sess.handleAckFrame(ack, protocol.Encryption1RTT)).To(Succeed())
2574	})
2575
2576	Context("handling tokens", func() {
2577		var mockTokenStore *MockTokenStore
2578
2579		BeforeEach(func() {
2580			mockTokenStore = NewMockTokenStore(mockCtrl)
2581			tlsConf = &tls.Config{ServerName: "server"}
2582			quicConf.TokenStore = mockTokenStore
2583			mockTokenStore.EXPECT().Pop(gomock.Any())
2584			quicConf.TokenStore = mockTokenStore
2585		})
2586
2587		It("handles NEW_TOKEN frames", func() {
2588			mockTokenStore.EXPECT().Put("server", &ClientToken{data: []byte("foobar")})
2589			Expect(sess.handleNewTokenFrame(&wire.NewTokenFrame{Token: []byte("foobar")})).To(Succeed())
2590		})
2591	})
2592
2593	Context("handling Version Negotiation", func() {
2594		getVNP := func(versions ...protocol.VersionNumber) *receivedPacket {
2595			b, err := wire.ComposeVersionNegotiation(srcConnID, destConnID, versions)
2596			Expect(err).ToNot(HaveOccurred())
2597			return &receivedPacket{
2598				data:   b,
2599				buffer: getPacketBuffer(),
2600			}
2601		}
2602
2603		It("closes and returns the right error", func() {
2604			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
2605			sess.sentPacketHandler = sph
2606			sph.EXPECT().ReceivedBytes(gomock.Any())
2607			sph.EXPECT().PeekPacketNumber(protocol.EncryptionInitial).Return(protocol.PacketNumber(128), protocol.PacketNumberLen4)
2608			sess.config.Versions = []protocol.VersionNumber{1234, 4321}
2609			errChan := make(chan error, 1)
2610			go func() {
2611				defer GinkgoRecover()
2612				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2613				errChan <- sess.run()
2614			}()
2615			sessionRunner.EXPECT().Remove(srcConnID)
2616			tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()).Do(func(hdr *wire.Header, versions []logging.VersionNumber) {
2617				Expect(hdr.Version).To(BeZero())
2618				Expect(versions).To(And(
2619					ContainElement(protocol.VersionNumber(4321)),
2620					ContainElement(protocol.VersionNumber(1337)),
2621				))
2622			})
2623			cryptoSetup.EXPECT().Close()
2624			Expect(sess.handlePacketImpl(getVNP(4321, 1337))).To(BeFalse())
2625			var err error
2626			Eventually(errChan).Should(Receive(&err))
2627			Expect(err).To(HaveOccurred())
2628			Expect(err).To(BeAssignableToTypeOf(&errCloseForRecreating{}))
2629			recreateErr := err.(*errCloseForRecreating)
2630			Expect(recreateErr.nextVersion).To(Equal(protocol.VersionNumber(4321)))
2631			Expect(recreateErr.nextPacketNumber).To(Equal(protocol.PacketNumber(128)))
2632		})
2633
2634		It("it closes when no matching version is found", func() {
2635			errChan := make(chan error, 1)
2636			go func() {
2637				defer GinkgoRecover()
2638				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2639				errChan <- sess.run()
2640			}()
2641			sessionRunner.EXPECT().Remove(srcConnID).MaxTimes(1)
2642			gomock.InOrder(
2643				tracer.EXPECT().ReceivedVersionNegotiationPacket(gomock.Any(), gomock.Any()),
2644				tracer.EXPECT().ClosedConnection(gomock.Any()).Do(func(e error) {
2645					var vnErr *VersionNegotiationError
2646					Expect(errors.As(e, &vnErr)).To(BeTrue())
2647					Expect(vnErr.Theirs).To(ContainElement(logging.VersionNumber(12345678)))
2648				}),
2649				tracer.EXPECT().Close(),
2650			)
2651			cryptoSetup.EXPECT().Close()
2652			Expect(sess.handlePacketImpl(getVNP(12345678))).To(BeFalse())
2653			var err error
2654			Eventually(errChan).Should(Receive(&err))
2655			Expect(err).To(HaveOccurred())
2656			Expect(err).ToNot(BeAssignableToTypeOf(errCloseForRecreating{}))
2657			Expect(err.Error()).To(ContainSubstring("no compatible QUIC version found"))
2658		})
2659
2660		It("ignores Version Negotiation packets that offer the current version", func() {
2661			p := getVNP(sess.version)
2662			tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, p.Size(), logging.PacketDropUnexpectedVersion)
2663			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2664		})
2665
2666		It("ignores unparseable Version Negotiation packets", func() {
2667			p := getVNP(sess.version)
2668			p.data = p.data[:len(p.data)-2]
2669			tracer.EXPECT().DroppedPacket(logging.PacketTypeVersionNegotiation, p.Size(), logging.PacketDropHeaderParseError)
2670			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2671		})
2672	})
2673
2674	Context("handling Retry", func() {
2675		origDestConnID := protocol.ConnectionID{8, 7, 6, 5, 4, 3, 2, 1}
2676
2677		var retryHdr *wire.ExtendedHeader
2678
2679		JustBeforeEach(func() {
2680			retryHdr = &wire.ExtendedHeader{
2681				Header: wire.Header{
2682					IsLongHeader:     true,
2683					Type:             protocol.PacketTypeRetry,
2684					SrcConnectionID:  protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
2685					DestConnectionID: protocol.ConnectionID{1, 2, 3, 4, 5, 6, 7, 8},
2686					Token:            []byte("foobar"),
2687					Version:          sess.version,
2688				},
2689			}
2690		})
2691
2692		getRetryTag := func(hdr *wire.ExtendedHeader) []byte {
2693			buf := &bytes.Buffer{}
2694			hdr.Write(buf, sess.version)
2695			return handshake.GetRetryIntegrityTag(buf.Bytes(), origDestConnID, hdr.Version)[:]
2696		}
2697
2698		It("handles Retry packets", func() {
2699			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
2700			sess.sentPacketHandler = sph
2701			sph.EXPECT().ResetForRetry()
2702			sph.EXPECT().ReceivedBytes(gomock.Any())
2703			cryptoSetup.EXPECT().ChangeConnectionID(protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef})
2704			packer.EXPECT().SetToken([]byte("foobar"))
2705			tracer.EXPECT().ReceivedRetry(gomock.Any()).Do(func(hdr *wire.Header) {
2706				Expect(hdr.DestConnectionID).To(Equal(retryHdr.DestConnectionID))
2707				Expect(hdr.SrcConnectionID).To(Equal(retryHdr.SrcConnectionID))
2708				Expect(hdr.Token).To(Equal(retryHdr.Token))
2709			})
2710			Expect(sess.handlePacketImpl(getPacket(retryHdr, getRetryTag(retryHdr)))).To(BeTrue())
2711		})
2712
2713		It("ignores Retry packets after receiving a regular packet", func() {
2714			sess.receivedFirstPacket = true
2715			p := getPacket(retryHdr, getRetryTag(retryHdr))
2716			tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket)
2717			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2718		})
2719
2720		It("ignores Retry packets if the server didn't change the connection ID", func() {
2721			retryHdr.SrcConnectionID = destConnID
2722			p := getPacket(retryHdr, getRetryTag(retryHdr))
2723			tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropUnexpectedPacket)
2724			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2725		})
2726
2727		It("ignores Retry packets with the a wrong Integrity tag", func() {
2728			tag := getRetryTag(retryHdr)
2729			tag[0]++
2730			p := getPacket(retryHdr, tag)
2731			tracer.EXPECT().DroppedPacket(logging.PacketTypeRetry, p.Size(), logging.PacketDropPayloadDecryptError)
2732			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2733		})
2734	})
2735
2736	Context("transport parameters", func() {
2737		var (
2738			closed  bool
2739			errChan chan error
2740		)
2741
2742		JustBeforeEach(func() {
2743			errChan = make(chan error, 1)
2744			closed = false
2745			go func() {
2746				defer GinkgoRecover()
2747				cryptoSetup.EXPECT().RunHandshake().MaxTimes(1)
2748				errChan <- sess.run()
2749				close(errChan)
2750			}()
2751		})
2752
2753		expectClose := func(applicationClose bool) {
2754			if !closed {
2755				sessionRunner.EXPECT().ReplaceWithClosed(gomock.Any(), gomock.Any()).Do(func(_ protocol.ConnectionID, s packetHandler) {
2756					Expect(s).To(BeAssignableToTypeOf(&closedLocalSession{}))
2757					s.shutdown()
2758				})
2759				if applicationClose {
2760					packer.EXPECT().PackApplicationClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil).MaxTimes(1)
2761				} else {
2762					packer.EXPECT().PackConnectionClose(gomock.Any()).Return(&coalescedPacket{buffer: getPacketBuffer()}, nil).MaxTimes(1)
2763				}
2764				cryptoSetup.EXPECT().Close()
2765				mconn.EXPECT().Write(gomock.Any())
2766				gomock.InOrder(
2767					tracer.EXPECT().ClosedConnection(gomock.Any()),
2768					tracer.EXPECT().Close(),
2769				)
2770			}
2771			closed = true
2772		}
2773
2774		AfterEach(func() {
2775			sess.shutdown()
2776			Eventually(sess.Context().Done()).Should(BeClosed())
2777			Eventually(errChan).Should(BeClosed())
2778		})
2779
2780		It("uses the preferred_address connection ID", func() {
2781			params := &wire.TransportParameters{
2782				OriginalDestinationConnectionID: destConnID,
2783				InitialSourceConnectionID:       destConnID,
2784				PreferredAddress: &wire.PreferredAddress{
2785					IPv4:                net.IPv4(127, 0, 0, 1),
2786					IPv6:                net.IP{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2787					ConnectionID:        protocol.ConnectionID{1, 2, 3, 4},
2788					StatelessResetToken: protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1},
2789				},
2790			}
2791			packer.EXPECT().HandleTransportParameters(gomock.Any())
2792			packer.EXPECT().PackCoalescedPacket().MaxTimes(1)
2793			tracer.EXPECT().ReceivedTransportParameters(params)
2794			sess.handleTransportParameters(params)
2795			sess.handleHandshakeComplete()
2796			// make sure the connection ID is not retired
2797			cf, _ := sess.framer.AppendControlFrames(nil, protocol.MaxByteCount)
2798			Expect(cf).To(BeEmpty())
2799			sessionRunner.EXPECT().AddResetToken(protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, sess)
2800			Expect(sess.connIDManager.Get()).To(Equal(protocol.ConnectionID{1, 2, 3, 4}))
2801			// shut down
2802			sessionRunner.EXPECT().RemoveResetToken(protocol.StatelessResetToken{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1})
2803			expectClose(true)
2804		})
2805
2806		It("uses the minimum of the peers' idle timeouts", func() {
2807			sess.config.MaxIdleTimeout = 19 * time.Second
2808			params := &wire.TransportParameters{
2809				OriginalDestinationConnectionID: destConnID,
2810				InitialSourceConnectionID:       destConnID,
2811				MaxIdleTimeout:                  18 * time.Second,
2812			}
2813			packer.EXPECT().HandleTransportParameters(gomock.Any())
2814			tracer.EXPECT().ReceivedTransportParameters(params)
2815			sess.handleTransportParameters(params)
2816			sess.handleHandshakeComplete()
2817			Expect(sess.idleTimeout).To(Equal(18 * time.Second))
2818			expectClose(true)
2819		})
2820
2821		It("errors if the transport parameters contain a wrong initial_source_connection_id", func() {
2822			sess.handshakeDestConnID = protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
2823			params := &wire.TransportParameters{
2824				OriginalDestinationConnectionID: destConnID,
2825				InitialSourceConnectionID:       protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad},
2826				StatelessResetToken:             &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2827			}
2828			expectClose(false)
2829			tracer.EXPECT().ReceivedTransportParameters(params)
2830			sess.handleTransportParameters(params)
2831			Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{
2832				ErrorCode:    qerr.TransportParameterError,
2833				ErrorMessage: "expected initial_source_connection_id to equal deadbeef, is decafbad",
2834			})))
2835		})
2836
2837		It("errors if the transport parameters don't contain the retry_source_connection_id, if a Retry was performed", func() {
2838			sess.retrySrcConnID = &protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
2839			params := &wire.TransportParameters{
2840				OriginalDestinationConnectionID: destConnID,
2841				InitialSourceConnectionID:       destConnID,
2842				StatelessResetToken:             &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2843			}
2844			expectClose(false)
2845			tracer.EXPECT().ReceivedTransportParameters(params)
2846			sess.handleTransportParameters(params)
2847			Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{
2848				ErrorCode:    qerr.TransportParameterError,
2849				ErrorMessage: "missing retry_source_connection_id",
2850			})))
2851		})
2852
2853		It("errors if the transport parameters contain the wrong retry_source_connection_id, if a Retry was performed", func() {
2854			sess.retrySrcConnID = &protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
2855			params := &wire.TransportParameters{
2856				OriginalDestinationConnectionID: destConnID,
2857				InitialSourceConnectionID:       destConnID,
2858				RetrySourceConnectionID:         &protocol.ConnectionID{0xde, 0xad, 0xc0, 0xde},
2859				StatelessResetToken:             &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2860			}
2861			expectClose(false)
2862			tracer.EXPECT().ReceivedTransportParameters(params)
2863			sess.handleTransportParameters(params)
2864			Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{
2865				ErrorCode:    qerr.TransportParameterError,
2866				ErrorMessage: "expected retry_source_connection_id to equal deadbeef, is deadc0de",
2867			})))
2868		})
2869
2870		It("errors if the transport parameters contain the retry_source_connection_id, if no Retry was performed", func() {
2871			params := &wire.TransportParameters{
2872				OriginalDestinationConnectionID: destConnID,
2873				InitialSourceConnectionID:       destConnID,
2874				RetrySourceConnectionID:         &protocol.ConnectionID{0xde, 0xad, 0xc0, 0xde},
2875				StatelessResetToken:             &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2876			}
2877			expectClose(false)
2878			tracer.EXPECT().ReceivedTransportParameters(params)
2879			sess.handleTransportParameters(params)
2880			Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{
2881				ErrorCode:    qerr.TransportParameterError,
2882				ErrorMessage: "received retry_source_connection_id, although no Retry was performed",
2883			})))
2884		})
2885
2886		It("errors if the transport parameters contain a wrong original_destination_connection_id", func() {
2887			sess.origDestConnID = protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
2888			params := &wire.TransportParameters{
2889				OriginalDestinationConnectionID: protocol.ConnectionID{0xde, 0xca, 0xfb, 0xad},
2890				InitialSourceConnectionID:       sess.handshakeDestConnID,
2891				StatelessResetToken:             &protocol.StatelessResetToken{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
2892			}
2893			expectClose(false)
2894			tracer.EXPECT().ReceivedTransportParameters(params)
2895			sess.handleTransportParameters(params)
2896			Eventually(errChan).Should(Receive(MatchError(&qerr.TransportError{
2897				ErrorCode:    qerr.TransportParameterError,
2898				ErrorMessage: "expected original_destination_connection_id to equal deadbeef, is decafbad",
2899			})))
2900		})
2901	})
2902
2903	Context("handling potentially injected packets", func() {
2904		var unpacker *MockUnpacker
2905
2906		getPacket := func(extHdr *wire.ExtendedHeader, data []byte) *receivedPacket {
2907			buf := &bytes.Buffer{}
2908			Expect(extHdr.Write(buf, sess.version)).To(Succeed())
2909			return &receivedPacket{
2910				data:   append(buf.Bytes(), data...),
2911				buffer: getPacketBuffer(),
2912			}
2913		}
2914
2915		// Convert an already packed raw packet into a receivedPacket
2916		wrapPacket := func(packet []byte) *receivedPacket {
2917			return &receivedPacket{
2918				data:   packet,
2919				buffer: getPacketBuffer(),
2920			}
2921		}
2922
2923		// Illustrates that attacker may inject an Initial packet with a different
2924		// source connection ID, causing endpoint to ignore a subsequent real Initial packets.
2925		It("ignores Initial packets with a different source connection ID", func() {
2926			// Modified from test "ignores packets with a different source connection ID"
2927			unpacker = NewMockUnpacker(mockCtrl)
2928			sess.unpacker = unpacker
2929
2930			hdr1 := &wire.ExtendedHeader{
2931				Header: wire.Header{
2932					IsLongHeader:     true,
2933					Type:             protocol.PacketTypeInitial,
2934					DestConnectionID: destConnID,
2935					SrcConnectionID:  srcConnID,
2936					Length:           1,
2937					Version:          sess.version,
2938				},
2939				PacketNumberLen: protocol.PacketNumberLen1,
2940				PacketNumber:    1,
2941			}
2942			hdr2 := &wire.ExtendedHeader{
2943				Header: wire.Header{
2944					IsLongHeader:     true,
2945					Type:             protocol.PacketTypeInitial,
2946					DestConnectionID: destConnID,
2947					SrcConnectionID:  protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef},
2948					Length:           1,
2949					Version:          sess.version,
2950				},
2951				PacketNumberLen: protocol.PacketNumberLen1,
2952				PacketNumber:    2,
2953			}
2954			Expect(hdr2.SrcConnectionID).ToNot(Equal(srcConnID))
2955			// Send one packet, which might change the connection ID.
2956			// only EXPECT one call to the unpacker
2957			unpacker.EXPECT().Unpack(gomock.Any(), gomock.Any(), gomock.Any()).Return(&unpackedPacket{
2958				encryptionLevel: protocol.EncryptionInitial,
2959				hdr:             hdr1,
2960				data:            []byte{0}, // one PADDING frame
2961			}, nil)
2962			tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any())
2963			Expect(sess.handlePacketImpl(getPacket(hdr1, nil))).To(BeTrue())
2964			// The next packet has to be ignored, since the source connection ID doesn't match.
2965			tracer.EXPECT().DroppedPacket(gomock.Any(), gomock.Any(), gomock.Any())
2966			Expect(sess.handlePacketImpl(getPacket(hdr2, nil))).To(BeFalse())
2967		})
2968
2969		It("ignores 0-RTT packets", func() {
2970			p := getPacket(&wire.ExtendedHeader{
2971				Header: wire.Header{
2972					IsLongHeader:     true,
2973					Type:             protocol.PacketType0RTT,
2974					DestConnectionID: srcConnID,
2975					Length:           2 + 6,
2976					Version:          sess.version,
2977				},
2978				PacketNumber:    0x42,
2979				PacketNumberLen: protocol.PacketNumberLen2,
2980			}, []byte("foobar"))
2981			tracer.EXPECT().DroppedPacket(logging.PacketType0RTT, p.Size(), gomock.Any())
2982			Expect(sess.handlePacketImpl(p)).To(BeFalse())
2983		})
2984
2985		// Illustrates that an injected Initial with an ACK frame for an unsent packet causes
2986		// the connection to immediately break down
2987		It("fails on Initial-level ACK for unsent packet", func() {
2988			ack := &wire.AckFrame{AckRanges: []wire.AckRange{{Smallest: 2, Largest: 2}}}
2989			initialPacket := testutils.ComposeInitialPacket(destConnID, srcConnID, sess.version, destConnID, []wire.Frame{ack})
2990			tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any())
2991			Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeFalse())
2992		})
2993
2994		// Illustrates that an injected Initial with a CONNECTION_CLOSE frame causes
2995		// the connection to immediately break down
2996		It("fails on Initial-level CONNECTION_CLOSE frame", func() {
2997			connCloseFrame := &wire.ConnectionCloseFrame{
2998				IsApplicationError: true,
2999				ReasonPhrase:       "mitm attacker",
3000			}
3001			initialPacket := testutils.ComposeInitialPacket(destConnID, srcConnID, sess.version, destConnID, []wire.Frame{connCloseFrame})
3002			tracer.EXPECT().ReceivedPacket(gomock.Any(), gomock.Any(), gomock.Any())
3003			Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeTrue())
3004		})
3005
3006		// Illustrates that attacker who injects a Retry packet and changes the connection ID
3007		// can cause subsequent real Initial packets to be ignored
3008		It("ignores Initial packets which use original source id, after accepting a Retry", func() {
3009			sph := mockackhandler.NewMockSentPacketHandler(mockCtrl)
3010			sess.sentPacketHandler = sph
3011			sph.EXPECT().ReceivedBytes(gomock.Any()).Times(2)
3012			sph.EXPECT().ResetForRetry()
3013			newSrcConnID := protocol.ConnectionID{0xde, 0xad, 0xbe, 0xef}
3014			cryptoSetup.EXPECT().ChangeConnectionID(newSrcConnID)
3015			packer.EXPECT().SetToken([]byte("foobar"))
3016
3017			tracer.EXPECT().ReceivedRetry(gomock.Any())
3018			sess.handlePacketImpl(wrapPacket(testutils.ComposeRetryPacket(newSrcConnID, destConnID, destConnID, []byte("foobar"), sess.version)))
3019			initialPacket := testutils.ComposeInitialPacket(sess.connIDManager.Get(), srcConnID, sess.version, sess.connIDManager.Get(), nil)
3020			tracer.EXPECT().DroppedPacket(gomock.Any(), gomock.Any(), gomock.Any())
3021			Expect(sess.handlePacketImpl(wrapPacket(initialPacket))).To(BeFalse())
3022		})
3023	})
3024})
3025