mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-04 12:47:36 +03:00
add a 0-RTT test case using non-zero length connection IDs
This commit is contained in:
parent
33a47fe661
commit
f25ec1b62c
1 changed files with 133 additions and 111 deletions
|
@ -125,7 +125,8 @@ var _ = Describe("0-RTT", func() {
|
||||||
transfer0RTTData := func(
|
transfer0RTTData := func(
|
||||||
ln quic.EarlyListener,
|
ln quic.EarlyListener,
|
||||||
proxyPort int,
|
proxyPort int,
|
||||||
clientConf *tls.Config,
|
clientTLSConf *tls.Config,
|
||||||
|
clientConf *quic.Config,
|
||||||
testdata []byte, // data to transfer
|
testdata []byte, // data to transfer
|
||||||
) {
|
) {
|
||||||
// now dial the second session, and use 0-RTT to send some data
|
// now dial the second session, and use 0-RTT to send some data
|
||||||
|
@ -144,10 +145,13 @@ var _ = Describe("0-RTT", func() {
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if clientConf == nil {
|
||||||
|
clientConf = getQuicConfig(&quic.Config{Versions: []protocol.VersionNumber{version}})
|
||||||
|
}
|
||||||
sess, err := quic.DialAddrEarly(
|
sess, err := quic.DialAddrEarly(
|
||||||
fmt.Sprintf("localhost:%d", proxyPort),
|
fmt.Sprintf("localhost:%d", proxyPort),
|
||||||
|
clientTLSConf,
|
||||||
clientConf,
|
clientConf,
|
||||||
getQuicConfig(&quic.Config{Versions: []protocol.VersionNumber{version}}),
|
|
||||||
)
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
defer sess.CloseWithError(0, "")
|
defer sess.CloseWithError(0, "")
|
||||||
|
@ -202,35 +206,62 @@ var _ = Describe("0-RTT", func() {
|
||||||
return zeroRTTPackets
|
return zeroRTTPackets
|
||||||
}
|
}
|
||||||
|
|
||||||
It("transfers 0-RTT data", func() {
|
for _, l := range []int{0, 15} {
|
||||||
tlsConf, clientConf := dialAndReceiveSessionTicket(nil)
|
connIDLen := l
|
||||||
|
|
||||||
tracer := newRcvdPacketTracer()
|
It(fmt.Sprintf("transfers 0-RTT data, with %d byte connection IDs", connIDLen), func() {
|
||||||
ln, err := quic.ListenAddrEarly(
|
tlsConf, clientTLSConf := dialAndReceiveSessionTicket(nil)
|
||||||
"localhost:0",
|
|
||||||
tlsConf,
|
|
||||||
getQuicConfig(&quic.Config{
|
|
||||||
Versions: []protocol.VersionNumber{version},
|
|
||||||
AcceptToken: func(_ net.Addr, _ *quic.Token) bool { return true },
|
|
||||||
Tracer: newTracer(func() logging.ConnectionTracer { return tracer }),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
defer ln.Close()
|
|
||||||
|
|
||||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
tracer := newRcvdPacketTracer()
|
||||||
defer proxy.Close()
|
ln, err := quic.ListenAddrEarly(
|
||||||
|
"localhost:0",
|
||||||
|
tlsConf,
|
||||||
|
getQuicConfig(&quic.Config{
|
||||||
|
Versions: []protocol.VersionNumber{version},
|
||||||
|
AcceptToken: func(_ net.Addr, _ *quic.Token) bool { return true },
|
||||||
|
Tracer: newTracer(func() logging.ConnectionTracer { return tracer }),
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
transfer0RTTData(ln, proxy.LocalPort(), clientConf, PRData)
|
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||||
|
defer proxy.Close()
|
||||||
|
|
||||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
transfer0RTTData(
|
||||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
ln,
|
||||||
Expect(num0RTT).ToNot(BeZero())
|
proxy.LocalPort(),
|
||||||
zeroRTTPackets := get0RTTPackets(tracer.getRcvdPackets())
|
clientTLSConf,
|
||||||
Expect(len(zeroRTTPackets)).To(BeNumerically(">", 10))
|
&quic.Config{
|
||||||
sort.Slice(zeroRTTPackets, func(i, j int) bool { return zeroRTTPackets[i] < zeroRTTPackets[j] })
|
ConnectionIDLength: connIDLen,
|
||||||
Expect(zeroRTTPackets[0]).To(Equal(protocol.PacketNumber(0)))
|
Versions: []protocol.VersionNumber{version},
|
||||||
})
|
},
|
||||||
|
PRData,
|
||||||
|
)
|
||||||
|
|
||||||
|
var numNewConnIDs int
|
||||||
|
for _, p := range tracer.getRcvdPackets() {
|
||||||
|
for _, f := range p.frames {
|
||||||
|
if _, ok := f.(*logging.NewConnectionIDFrame); ok {
|
||||||
|
numNewConnIDs++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if connIDLen == 0 {
|
||||||
|
Expect(numNewConnIDs).To(BeZero())
|
||||||
|
} else {
|
||||||
|
Expect(numNewConnIDs).ToNot(BeZero())
|
||||||
|
}
|
||||||
|
|
||||||
|
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||||
|
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||||
|
Expect(num0RTT).ToNot(BeZero())
|
||||||
|
zeroRTTPackets := get0RTTPackets(tracer.getRcvdPackets())
|
||||||
|
Expect(len(zeroRTTPackets)).To(BeNumerically(">", 10))
|
||||||
|
sort.Slice(zeroRTTPackets, func(i, j int) bool { return zeroRTTPackets[i] < zeroRTTPackets[j] })
|
||||||
|
Expect(zeroRTTPackets[0]).To(Equal(protocol.PacketNumber(0)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Test that data intended to be sent with 1-RTT protection is not sent in 0-RTT packets.
|
// Test that data intended to be sent with 1-RTT protection is not sent in 0-RTT packets.
|
||||||
It("waits until a session until the handshake is done", func() {
|
It("waits until a session until the handshake is done", func() {
|
||||||
|
@ -353,7 +384,7 @@ var _ = Describe("0-RTT", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
|
|
||||||
transfer0RTTData(ln, proxy.LocalPort(), clientConf, PRData)
|
transfer0RTTData(ln, proxy.LocalPort(), clientConf, nil, PRData)
|
||||||
|
|
||||||
num0RTT := atomic.LoadUint32(&num0RTTPackets)
|
num0RTT := atomic.LoadUint32(&num0RTTPackets)
|
||||||
numDropped := atomic.LoadUint32(&num0RTTDropped)
|
numDropped := atomic.LoadUint32(&num0RTTDropped)
|
||||||
|
@ -427,7 +458,7 @@ var _ = Describe("0-RTT", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
|
|
||||||
transfer0RTTData(ln, proxy.LocalPort(), clientConf, GeneratePRData(5000)) // ~5 packets
|
transfer0RTTData(ln, proxy.LocalPort(), clientConf, nil, GeneratePRData(5000)) // ~5 packets
|
||||||
|
|
||||||
mutex.Lock()
|
mutex.Lock()
|
||||||
defer mutex.Unlock()
|
defer mutex.Unlock()
|
||||||
|
@ -629,93 +660,84 @@ var _ = Describe("0-RTT", func() {
|
||||||
Entry("doesn't reject 0-RTT when the server's transport connection flow control limit increased", func(c *quic.Config, limit uint64) { c.InitialConnectionReceiveWindow = limit }),
|
Entry("doesn't reject 0-RTT when the server's transport connection flow control limit increased", func(c *quic.Config, limit uint64) { c.InitialConnectionReceiveWindow = limit }),
|
||||||
)
|
)
|
||||||
|
|
||||||
It("correctly deals with 0-RTT rejections", func() {
|
for _, l := range []int{0, 15} {
|
||||||
tlsConf, clientConf := dialAndReceiveSessionTicket(nil)
|
connIDLen := l
|
||||||
// now dial new connection with different transport parameters
|
|
||||||
tracer := newRcvdPacketTracer()
|
|
||||||
ln, err := quic.ListenAddrEarly(
|
|
||||||
"localhost:0",
|
|
||||||
tlsConf,
|
|
||||||
getQuicConfig(&quic.Config{
|
|
||||||
Versions: []protocol.VersionNumber{version},
|
|
||||||
MaxIncomingUniStreams: 1,
|
|
||||||
Tracer: newTracer(func() logging.ConnectionTracer { return tracer }),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
defer ln.Close()
|
|
||||||
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
|
||||||
defer proxy.Close()
|
|
||||||
|
|
||||||
done := make(chan struct{})
|
It(fmt.Sprintf("correctly deals with 0-RTT rejections, for %d byte connection IDs", connIDLen), func() {
|
||||||
go func() {
|
tlsConf, clientConf := dialAndReceiveSessionTicket(nil)
|
||||||
defer GinkgoRecover()
|
// now dial new connection with different transport parameters
|
||||||
defer close(done)
|
tracer := newRcvdPacketTracer()
|
||||||
sess, err := ln.Accept(context.Background())
|
ln, err := quic.ListenAddrEarly(
|
||||||
|
"localhost:0",
|
||||||
|
tlsConf,
|
||||||
|
getQuicConfig(&quic.Config{
|
||||||
|
Versions: []protocol.VersionNumber{version},
|
||||||
|
MaxIncomingUniStreams: 1,
|
||||||
|
Tracer: newTracer(func() logging.ConnectionTracer { return tracer }),
|
||||||
|
}),
|
||||||
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
str, err := sess.AcceptUniStream(context.Background())
|
defer ln.Close()
|
||||||
|
proxy, num0RTTPackets := runCountingProxy(ln.Addr().(*net.UDPAddr).Port)
|
||||||
|
defer proxy.Close()
|
||||||
|
|
||||||
|
sess, err := quic.DialAddrEarly(
|
||||||
|
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
||||||
|
clientConf,
|
||||||
|
getQuicConfig(&quic.Config{Versions: []protocol.VersionNumber{version}}),
|
||||||
|
)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
data, err := ioutil.ReadAll(str)
|
// The client remembers that it was allowed to open 2 uni-directional streams.
|
||||||
|
firstStr, err := sess.OpenUniStream()
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
Expect(string(data)).To(Equal("second flight"))
|
written := make(chan struct{}, 2)
|
||||||
|
go func() {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
defer func() { written <- struct{}{} }()
|
||||||
|
_, err := firstStr.Write([]byte("first flight"))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
}()
|
||||||
|
secondStr, err := sess.OpenUniStream()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
go func() {
|
||||||
|
defer GinkgoRecover()
|
||||||
|
defer func() { written <- struct{}{} }()
|
||||||
|
_, err := secondStr.Write([]byte("first flight"))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
}()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||||
|
defer cancel()
|
||||||
|
_, err = sess.AcceptStream(ctx)
|
||||||
|
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
||||||
|
Eventually(written).Should(Receive())
|
||||||
|
Eventually(written).Should(Receive())
|
||||||
|
_, err = firstStr.Write([]byte("foobar"))
|
||||||
|
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
||||||
|
_, err = sess.OpenUniStream()
|
||||||
|
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
||||||
|
|
||||||
|
_, err = sess.AcceptStream(ctx)
|
||||||
|
Expect(err).To(Equal(quic.Err0RTTRejected))
|
||||||
|
|
||||||
|
newSess := sess.NextSession()
|
||||||
|
str, err := newSess.OpenUniStream()
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
_, err = newSess.OpenUniStream()
|
||||||
|
Expect(err).To(HaveOccurred())
|
||||||
|
Expect(err.Error()).To(ContainSubstring("too many open streams"))
|
||||||
|
_, err = str.Write([]byte("second flight"))
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(str.Close()).To(Succeed())
|
||||||
Expect(sess.CloseWithError(0, "")).To(Succeed())
|
Expect(sess.CloseWithError(0, "")).To(Succeed())
|
||||||
}()
|
|
||||||
|
|
||||||
sess, err := quic.DialAddrEarly(
|
// The client should send 0-RTT packets, but the server doesn't process them.
|
||||||
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
||||||
clientConf,
|
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
||||||
getQuicConfig(&quic.Config{Versions: []protocol.VersionNumber{version}}),
|
Expect(num0RTT).ToNot(BeZero())
|
||||||
)
|
Expect(get0RTTPackets(tracer.getRcvdPackets())).To(BeEmpty())
|
||||||
Expect(err).ToNot(HaveOccurred())
|
})
|
||||||
// The client remembers that it was allowed to open 2 uni-directional streams.
|
}
|
||||||
firstStr, err := sess.OpenUniStream()
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
written := make(chan struct{}, 2)
|
|
||||||
go func() {
|
|
||||||
defer GinkgoRecover()
|
|
||||||
defer func() { written <- struct{}{} }()
|
|
||||||
_, err := firstStr.Write([]byte("first flight"))
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
}()
|
|
||||||
secondStr, err := sess.OpenUniStream()
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
go func() {
|
|
||||||
defer GinkgoRecover()
|
|
||||||
defer func() { written <- struct{}{} }()
|
|
||||||
_, err := secondStr.Write([]byte("first flight"))
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
}()
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
|
||||||
defer cancel()
|
|
||||||
_, err = sess.AcceptStream(ctx)
|
|
||||||
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
|
||||||
Eventually(written).Should(Receive())
|
|
||||||
Eventually(written).Should(Receive())
|
|
||||||
_, err = firstStr.Write([]byte("foobar"))
|
|
||||||
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
|
||||||
_, err = sess.OpenUniStream()
|
|
||||||
Expect(err).To(MatchError(quic.Err0RTTRejected))
|
|
||||||
|
|
||||||
newSess := sess.NextSession()
|
|
||||||
str, err := newSess.OpenUniStream()
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
_, err = newSess.OpenUniStream()
|
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(err.Error()).To(ContainSubstring("too many open streams"))
|
|
||||||
_, err = str.Write([]byte("second flight"))
|
|
||||||
Expect(err).ToNot(HaveOccurred())
|
|
||||||
Expect(str.Close()).To(Succeed())
|
|
||||||
|
|
||||||
Eventually(done).Should(BeClosed())
|
|
||||||
Eventually(sess.Context().Done()).Should(BeClosed())
|
|
||||||
|
|
||||||
// The client should send 0-RTT packets, but the server doesn't process them.
|
|
||||||
num0RTT := atomic.LoadUint32(num0RTTPackets)
|
|
||||||
fmt.Fprintf(GinkgoWriter, "Sent %d 0-RTT packets.", num0RTT)
|
|
||||||
Expect(num0RTT).ToNot(BeZero())
|
|
||||||
Expect(get0RTTPackets(tracer.getRcvdPackets())).To(BeEmpty())
|
|
||||||
})
|
|
||||||
|
|
||||||
It("queues 0-RTT packets, if the Initial is delayed", func() {
|
It("queues 0-RTT packets, if the Initial is delayed", func() {
|
||||||
tlsConf, clientConf := dialAndReceiveSessionTicket(nil)
|
tlsConf, clientConf := dialAndReceiveSessionTicket(nil)
|
||||||
|
@ -744,7 +766,7 @@ var _ = Describe("0-RTT", func() {
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
defer proxy.Close()
|
defer proxy.Close()
|
||||||
|
|
||||||
transfer0RTTData(ln, proxy.LocalPort(), clientConf, PRData)
|
transfer0RTTData(ln, proxy.LocalPort(), clientConf, nil, PRData)
|
||||||
|
|
||||||
Expect(tracer.rcvdPackets[0].hdr.Type).To(Equal(protocol.PacketTypeInitial))
|
Expect(tracer.rcvdPackets[0].hdr.Type).To(Equal(protocol.PacketTypeInitial))
|
||||||
zeroRTTPackets := get0RTTPackets(tracer.getRcvdPackets())
|
zeroRTTPackets := get0RTTPackets(tracer.getRcvdPackets())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue