mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-02 19:57:35 +03:00
109 lines
3 KiB
Go
109 lines
3 KiB
Go
package self_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/lucas-clemente/quic-go"
|
|
quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy"
|
|
"github.com/lucas-clemente/quic-go/internal/utils"
|
|
|
|
. "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() {
|
|
statelessResetKey := make([]byte, 32)
|
|
rand.Read(statelessResetKey)
|
|
serverConfig := getQuicConfig(&quic.Config{StatelessResetKey: statelessResetKey})
|
|
|
|
ln, err := quic.ListenAddr("localhost:0", getTLSConfig(), serverConfig)
|
|
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
|
|
ln.Close()
|
|
}()
|
|
|
|
drop := utils.AtomicBool{}
|
|
|
|
proxy, err := quicproxy.NewQuicProxy("localhost:0", &quicproxy.Opts{
|
|
RemoteAddr: fmt.Sprintf("localhost:%d", serverPort),
|
|
DropPacket: func(quicproxy.Direction, []byte) bool {
|
|
return drop.Get()
|
|
},
|
|
})
|
|
Expect(err).ToNot(HaveOccurred())
|
|
defer proxy.Close()
|
|
|
|
conn, err := quic.DialAddr(
|
|
fmt.Sprintf("localhost:%d", proxy.LocalPort()),
|
|
getTLSClientConfig(),
|
|
getQuicConfig(&quic.Config{
|
|
ConnectionIDLength: connIDLen,
|
|
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.Set(true)
|
|
close(closeServer)
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
ln2, err := quic.ListenAddr(
|
|
fmt.Sprintf("localhost:%d", serverPort),
|
|
getTLSConfig(),
|
|
serverConfig,
|
|
)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
drop.Set(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())
|
|
statelessResetErr := &quic.StatelessResetError{}
|
|
Expect(errors.As(serr, &statelessResetErr)).To(BeTrue())
|
|
Expect(ln2.Close()).To(Succeed())
|
|
Eventually(acceptStopped).Should(BeClosed())
|
|
})
|
|
}
|
|
})
|