mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-02 19:57:35 +03:00
uTLS is not yet bumped to the new version, so this commit breaks the dependencies relationship by getting rid of the local replace.
126 lines
3.7 KiB
Go
126 lines
3.7 KiB
Go
package self_test
|
|
|
|
import (
|
|
"context"
|
|
"crypto/rand"
|
|
"fmt"
|
|
"net"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
quic "github.com/refraction-networking/uquic"
|
|
quicproxy "github.com/refraction-networking/uquic/integrationtests/tools/proxy"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("Stateless Resets", func() {
|
|
connIDLens := []int{0, 10}
|
|
|
|
for i := range connIDLens {
|
|
connIDLen := connIDLens[i]
|
|
|
|
It(fmt.Sprintf("sends and recognizes stateless resets, for %d byte connection IDs", connIDLen), func() {
|
|
var statelessResetKey quic.StatelessResetKey
|
|
rand.Read(statelessResetKey[:])
|
|
|
|
c, err := net.ListenUDP("udp", nil)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
tr := &quic.Transport{
|
|
Conn: c,
|
|
StatelessResetKey: &statelessResetKey,
|
|
ConnectionIDLength: connIDLen,
|
|
}
|
|
defer tr.Close()
|
|
ln, err := tr.Listen(getTLSConfig(), getQuicConfig(nil))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
serverPort := ln.Addr().(*net.UDPAddr).Port
|
|
|
|
closeServer := make(chan struct{})
|
|
|
|
go func() {
|
|
defer GinkgoRecover()
|
|
conn, err := ln.Accept(context.Background())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
str, err := conn.OpenStream()
|
|
Expect(err).ToNot(HaveOccurred())
|
|
_, err = str.Write([]byte("foobar"))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
<-closeServer
|
|
Expect(ln.Close()).To(Succeed())
|
|
Expect(tr.Close()).To(Succeed())
|
|
}()
|
|
|
|
var drop atomic.Bool
|
|
proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{
|
|
RemoteAddr: fmt.Sprintf("localhost:%d", serverPort),
|
|
DropPacket: func(quicproxy.Direction, []byte) bool {
|
|
return drop.Load()
|
|
},
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer proxy.Close()
|
|
|
|
addr, err := net.ResolveUDPAddr("udp", "localhost:0")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
udpConn, err := net.ListenUDP("udp", addr)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer udpConn.Close()
|
|
cl := &quic.Transport{
|
|
Conn: udpConn,
|
|
ConnectionIDLength: connIDLen,
|
|
}
|
|
defer cl.Close()
|
|
conn, err := cl.Dial(
|
|
context.Background(),
|
|
&net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: proxy.LocalPort()},
|
|
getTLSClientConfig(),
|
|
getQuicConfig(&quic.Config{MaxIdleTimeout: 2 * time.Second}),
|
|
)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
str, err := conn.AcceptStream(context.Background())
|
|
Expect(err).ToNot(HaveOccurred())
|
|
data := make([]byte, 6)
|
|
_, err = str.Read(data)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(data).To(Equal([]byte("foobar")))
|
|
|
|
// make sure that the CONNECTION_CLOSE is dropped
|
|
drop.Store(true)
|
|
close(closeServer)
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
// We need to create a new Transport here, since the old one is still sending out
|
|
// CONNECTION_CLOSE packets for (recently) closed connections).
|
|
tr2 := &quic.Transport{
|
|
Conn: c,
|
|
ConnectionIDLength: connIDLen,
|
|
StatelessResetKey: &statelessResetKey,
|
|
}
|
|
defer tr2.Close()
|
|
ln2, err := tr2.Listen(getTLSConfig(), getQuicConfig(nil))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
drop.Store(false)
|
|
|
|
acceptStopped := make(chan struct{})
|
|
go func() {
|
|
defer GinkgoRecover()
|
|
_, err := ln2.Accept(context.Background())
|
|
Expect(err).To(HaveOccurred())
|
|
close(acceptStopped)
|
|
}()
|
|
|
|
// Trigger something (not too small) to be sent, so that we receive the stateless reset.
|
|
// If the client already sent another packet, it might already have received a packet.
|
|
_, serr := str.Write([]byte("Lorem ipsum dolor sit amet."))
|
|
if serr == nil {
|
|
_, serr = str.Read([]byte{0})
|
|
}
|
|
Expect(serr).To(HaveOccurred())
|
|
Expect(serr).To(BeAssignableToTypeOf(&quic.StatelessResetError{}))
|
|
Expect(ln2.Close()).To(Succeed())
|
|
Eventually(acceptStopped).Should(BeClosed())
|
|
})
|
|
}
|
|
})
|