| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
- // SPDX-License-Identifier: MIT
- //go:build !js
- // +build !js
- package ice
- import (
- "net"
- "testing"
- "time"
- "github.com/pion/logging"
- "github.com/pion/transport/v2/stdnet"
- "github.com/pion/transport/v2/test"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- )
- func getLocalIPAddress(t *testing.T, networkType NetworkType) net.IP {
- net, err := stdnet.NewNet()
- require.NoError(t, err)
- localIPs, err := localInterfaces(net, nil, nil, []NetworkType{networkType}, false)
- require.NoError(t, err)
- require.NotEmpty(t, localIPs)
- return localIPs[0]
- }
- func ipv6Available(t *testing.T) bool {
- net, err := stdnet.NewNet()
- require.NoError(t, err)
- localIPs, err := localInterfaces(net, nil, nil, []NetworkType{NetworkTypeTCP6}, false)
- require.NoError(t, err)
- return len(localIPs) > 0
- }
- func TestActiveTCP(t *testing.T) {
- report := test.CheckRoutines(t)
- defer report()
- lim := test.TimeOut(time.Second * 5)
- defer lim.Stop()
- const listenPort = 7686
- type testCase struct {
- name string
- networkTypes []NetworkType
- listenIPAddress net.IP
- selectedPairNetworkType string
- }
- testCases := []testCase{
- {
- name: "TCP4 connection",
- networkTypes: []NetworkType{NetworkTypeTCP4},
- listenIPAddress: getLocalIPAddress(t, NetworkTypeTCP4),
- selectedPairNetworkType: tcp,
- },
- {
- name: "UDP is preferred over TCP4", // This fails some time
- networkTypes: supportedNetworkTypes(),
- listenIPAddress: getLocalIPAddress(t, NetworkTypeTCP4),
- selectedPairNetworkType: udp,
- },
- }
- if ipv6Available(t) {
- testCases = append(testCases,
- testCase{
- name: "TCP6 connection",
- networkTypes: []NetworkType{NetworkTypeTCP6},
- listenIPAddress: getLocalIPAddress(t, NetworkTypeTCP6),
- selectedPairNetworkType: tcp,
- },
- testCase{
- name: "UDP is preferred over TCP6", // This fails some time
- networkTypes: supportedNetworkTypes(),
- listenIPAddress: getLocalIPAddress(t, NetworkTypeTCP6),
- selectedPairNetworkType: udp,
- },
- )
- }
- for _, testCase := range testCases {
- t.Run(testCase.name, func(t *testing.T) {
- r := require.New(t)
- listener, err := net.ListenTCP("tcp", &net.TCPAddr{
- IP: testCase.listenIPAddress,
- Port: listenPort,
- })
- r.NoError(err)
- defer func() {
- _ = listener.Close()
- }()
- loggerFactory := logging.NewDefaultLoggerFactory()
- tcpMux := NewTCPMuxDefault(TCPMuxParams{
- Listener: listener,
- Logger: loggerFactory.NewLogger("passive-ice-tcp-mux"),
- ReadBufferSize: 20,
- })
- defer func() {
- _ = tcpMux.Close()
- }()
- r.NotNil(tcpMux.LocalAddr(), "tcpMux.LocalAddr() is nil")
- hostAcceptanceMinWait := 100 * time.Millisecond
- passiveAgent, err := NewAgent(&AgentConfig{
- TCPMux: tcpMux,
- CandidateTypes: []CandidateType{CandidateTypeHost},
- NetworkTypes: testCase.networkTypes,
- LoggerFactory: loggerFactory,
- IncludeLoopback: true,
- HostAcceptanceMinWait: &hostAcceptanceMinWait,
- })
- r.NoError(err)
- r.NotNil(passiveAgent)
- activeAgent, err := NewAgent(&AgentConfig{
- CandidateTypes: []CandidateType{CandidateTypeHost},
- NetworkTypes: testCase.networkTypes,
- LoggerFactory: loggerFactory,
- HostAcceptanceMinWait: &hostAcceptanceMinWait,
- })
- r.NoError(err)
- r.NotNil(activeAgent)
- passiveAgentConn, activeAgenConn := connect(passiveAgent, activeAgent)
- r.NotNil(passiveAgentConn)
- r.NotNil(activeAgenConn)
- pair := passiveAgent.getSelectedPair()
- r.NotNil(pair)
- r.Equal(testCase.selectedPairNetworkType, pair.Local.NetworkType().NetworkShort())
- foo := []byte("foo")
- _, err = passiveAgentConn.Write(foo)
- r.NoError(err)
- buffer := make([]byte, 1024)
- n, err := activeAgenConn.Read(buffer)
- r.NoError(err)
- r.Equal(foo, buffer[:n])
- bar := []byte("bar")
- _, err = activeAgenConn.Write(bar)
- r.NoError(err)
- n, err = passiveAgentConn.Read(buffer)
- r.NoError(err)
- r.Equal(bar, buffer[:n])
- r.NoError(activeAgenConn.Close())
- r.NoError(passiveAgentConn.Close())
- })
- }
- }
- // Assert that Active TCP connectivity isn't established inside
- // the main thread of the Agent
- func TestActiveTCP_NonBlocking(t *testing.T) {
- report := test.CheckRoutines(t)
- defer report()
- lim := test.TimeOut(time.Second * 5)
- defer lim.Stop()
- cfg := &AgentConfig{
- NetworkTypes: supportedNetworkTypes(),
- }
- aAgent, err := NewAgent(cfg)
- if err != nil {
- t.Error(err)
- }
- bAgent, err := NewAgent(cfg)
- if err != nil {
- t.Error(err)
- }
- isConnected := make(chan interface{})
- err = aAgent.OnConnectionStateChange(func(c ConnectionState) {
- if c == ConnectionStateConnected {
- close(isConnected)
- }
- })
- if err != nil {
- t.Error(err)
- }
- // Add a invalid ice-tcp candidate to each
- invalidCandidate, err := UnmarshalCandidate("1052353102 1 tcp 1675624447 192.0.2.1 8080 typ host tcptype passive")
- if err != nil {
- t.Fatal(err)
- }
- assert.NoError(t, aAgent.AddRemoteCandidate(invalidCandidate))
- assert.NoError(t, bAgent.AddRemoteCandidate(invalidCandidate))
- connect(aAgent, bAgent)
- <-isConnected
- assert.NoError(t, aAgent.Close())
- assert.NoError(t, bAgent.Close())
- }
|