| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- package e2e
- import (
- "crypto/tls"
- "fmt"
- "math/rand"
- "testing"
- "time"
- "github.com/pion/dtls/v2"
- "github.com/pion/dtls/v2/pkg/crypto/selfsign"
- transportTest "github.com/pion/transport/test"
- )
- const (
- flightInterval = time.Millisecond * 100
- lossyTestTimeout = 30 * time.Second
- )
- /*
- DTLS Client/Server over a lossy transport, just asserts it can handle at increasing increments
- */
- func TestPionE2ELossy(t *testing.T) {
- // Check for leaking routines
- report := transportTest.CheckRoutines(t)
- defer report()
- type runResult struct {
- dtlsConn *dtls.Conn
- err error
- }
- serverCert, err := selfsign.GenerateSelfSigned()
- if err != nil {
- t.Fatal(err)
- }
- clientCert, err := selfsign.GenerateSelfSigned()
- if err != nil {
- t.Fatal(err)
- }
- for _, test := range []struct {
- LossChanceRange int
- DoClientAuth bool
- CipherSuites []dtls.CipherSuiteID
- MTU int
- }{
- {
- LossChanceRange: 0,
- },
- {
- LossChanceRange: 10,
- },
- {
- LossChanceRange: 20,
- },
- {
- LossChanceRange: 50,
- },
- {
- LossChanceRange: 0,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 10,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 20,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 50,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 0,
- CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- },
- {
- LossChanceRange: 10,
- CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- },
- {
- LossChanceRange: 20,
- CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- },
- {
- LossChanceRange: 50,
- CipherSuites: []dtls.CipherSuiteID{dtls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
- },
- {
- LossChanceRange: 10,
- MTU: 100,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 20,
- MTU: 100,
- DoClientAuth: true,
- },
- {
- LossChanceRange: 50,
- MTU: 100,
- DoClientAuth: true,
- },
- } {
- name := fmt.Sprintf("Loss%d_MTU%d", test.LossChanceRange, test.MTU)
- if test.DoClientAuth {
- name += "_WithCliAuth"
- }
- for _, ciph := range test.CipherSuites {
- name += "_With" + ciph.String()
- }
- test := test
- t.Run(name, func(t *testing.T) {
- // Limit runtime in case of deadlocks
- lim := transportTest.TimeOut(lossyTestTimeout + time.Second)
- defer lim.Stop()
- rand.Seed(time.Now().UTC().UnixNano())
- chosenLoss := rand.Intn(9) + test.LossChanceRange //nolint:gosec
- serverDone := make(chan runResult)
- clientDone := make(chan runResult)
- br := transportTest.NewBridge()
- if err = br.SetLossChance(chosenLoss); err != nil {
- t.Fatal(err)
- }
- go func() {
- cfg := &dtls.Config{
- FlightInterval: flightInterval,
- CipherSuites: test.CipherSuites,
- InsecureSkipVerify: true,
- MTU: test.MTU,
- }
- if test.DoClientAuth {
- cfg.Certificates = []tls.Certificate{clientCert}
- }
- client, startupErr := dtls.Client(br.GetConn0(), cfg)
- clientDone <- runResult{client, startupErr}
- }()
- go func() {
- cfg := &dtls.Config{
- Certificates: []tls.Certificate{serverCert},
- FlightInterval: flightInterval,
- MTU: test.MTU,
- }
- if test.DoClientAuth {
- cfg.ClientAuth = dtls.RequireAnyClientCert
- }
- server, startupErr := dtls.Server(br.GetConn1(), cfg)
- serverDone <- runResult{server, startupErr}
- }()
- testTimer := time.NewTimer(lossyTestTimeout)
- var serverConn, clientConn *dtls.Conn
- defer func() {
- if serverConn != nil {
- if err = serverConn.Close(); err != nil {
- t.Error(err)
- }
- }
- if clientConn != nil {
- if err = clientConn.Close(); err != nil {
- t.Error(err)
- }
- }
- }()
- for {
- if serverConn != nil && clientConn != nil {
- break
- }
- br.Tick()
- select {
- case serverResult := <-serverDone:
- if serverResult.err != nil {
- t.Errorf("Fail, serverError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", clientConn != nil, serverConn != nil, chosenLoss, serverResult.err)
- return
- }
- serverConn = serverResult.dtlsConn
- case clientResult := <-clientDone:
- if clientResult.err != nil {
- t.Errorf("Fail, clientError: clientComplete(%t) serverComplete(%t) LossChance(%d) error(%v)", clientConn != nil, serverConn != nil, chosenLoss, clientResult.err)
- return
- }
- clientConn = clientResult.dtlsConn
- case <-testTimer.C:
- t.Errorf("Test expired: clientComplete(%t) serverComplete(%t) LossChance(%d)", clientConn != nil, serverConn != nil, chosenLoss)
- return
- case <-time.After(10 * time.Millisecond):
- }
- }
- })
- }
- }
|