diff --git a/agent.go b/agent.go index 94b3d8f..12ffd59 100644 --- a/agent.go +++ b/agent.go @@ -119,6 +119,10 @@ type AgentConfig struct { // when this is nil, it defaults to 10 seconds. // A keepalive interval of 0 means we never send keepalive packets KeepaliveInterval *time.Duration + + // NetworkTypes is an optional configuration for disabling or enablding + // support for specific network types. + NetworkTypes []NetworkType } // NewAgent creates a new Agent @@ -158,8 +162,8 @@ func NewAgent(config *AgentConfig) (*Agent, error) { } // Initialize local candidates - a.gatherCandidatesLocal() - a.gatherCandidatesReflective(config.Urls) + a.gatherCandidatesLocal(config.NetworkTypes) + a.gatherCandidatesReflective(config.Urls, config.NetworkTypes) go a.taskLoop() return a, nil @@ -211,8 +215,8 @@ func (a *Agent) listenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, err return nil, ErrPort } -func (a *Agent) gatherCandidatesLocal() { - localIPs := localInterfaces() +func (a *Agent) gatherCandidatesLocal(networkTypes []NetworkType) { + localIPs := localInterfaces(networkTypes) for _, ip := range localIPs { for _, network := range supportedNetworks { conn, err := a.listenUDP(network, &net.UDPAddr{IP: ip, Port: 0}) @@ -238,8 +242,8 @@ func (a *Agent) gatherCandidatesLocal() { } } -func (a *Agent) gatherCandidatesReflective(urls []*URL) { - for _, networkType := range supportedNetworkTypes { +func (a *Agent) gatherCandidatesReflective(urls []*URL, networkTypes []NetworkType) { + for _, networkType := range networkTypes { network := networkType.String() for _, url := range urls { switch url.Scheme { diff --git a/networktype.go b/networktype.go index 9847995..48f5cf6 100644 --- a/networktype.go +++ b/networktype.go @@ -30,13 +30,13 @@ const ( // NetworkTypeUDP4 indicates UDP over IPv4. NetworkTypeUDP4 NetworkType = iota + 1 - // NetworkTypeUDP6 indicates UDP over IPv4. + // NetworkTypeUDP6 indicates UDP over IPv6. NetworkTypeUDP6 // NetworkTypeTCP4 indicates TCP over IPv4. NetworkTypeTCP4 - // NetworkTypeTCP6 indicates TCP over IPv4. + // NetworkTypeTCP6 indicates TCP over IPv6. NetworkTypeTCP6 ) @@ -78,6 +78,28 @@ func (t NetworkType) IsReliable() bool { return false } +// IsIPv4 returns whether the network type is IPv4 or not. +func (t NetworkType) IsIPv4() bool { + switch t { + case NetworkTypeUDP4, NetworkTypeTCP4: + return true + case NetworkTypeUDP6, NetworkTypeTCP6: + return false + } + return false +} + +// IsIPv6 returns whether the network type is IPv6 or not. +func (t NetworkType) IsIPv6() bool { + switch t { + case NetworkTypeUDP4, NetworkTypeTCP4: + return false + case NetworkTypeUDP6, NetworkTypeTCP6: + return true + } + return false +} + // determineNetworkType determines the type of network based on // the short network string and an IP address. func determineNetworkType(network string, ip net.IP) (NetworkType, error) { diff --git a/transport_test.go b/transport_test.go index d35e99c..a66ab5a 100644 --- a/transport_test.go +++ b/transport_test.go @@ -33,7 +33,7 @@ func testTimeout(t *testing.T, c *Conn, timeout time.Duration) { }) if err != nil { - //we should never get here. + // we should never get here. panic(err) } @@ -59,7 +59,7 @@ func TestTimeout(t *testing.T) { err := cb.Close() if err != nil { - //we should never get here. + // we should never get here. panic(err) } @@ -69,7 +69,7 @@ func TestTimeout(t *testing.T) { err = cb.Close() if err != nil { - //we should never get here. + // we should never get here. panic(err) } @@ -81,13 +81,13 @@ func TestReadClosed(t *testing.T) { err := ca.Close() if err != nil { - //we should never get here. + // we should never get here. panic(err) } err = cb.Close() if err != nil { - //we should never get here. + // we should never get here. panic(err) } @@ -191,7 +191,10 @@ func pipe() (*Conn, *Conn) { aNotifier, aConnected := onConnected() bNotifier, bConnected := onConnected() - aAgent, err := NewAgent(&AgentConfig{Urls: urls}) + aAgent, err := NewAgent(&AgentConfig{ + Urls: urls, + NetworkTypes: supportedNetworkTypes, + }) if err != nil { panic(err) } @@ -200,7 +203,10 @@ func pipe() (*Conn, *Conn) { panic(err) } - bAgent, err := NewAgent(&AgentConfig{Urls: urls}) + bAgent, err := NewAgent(&AgentConfig{ + Urls: urls, + NetworkTypes: supportedNetworkTypes, + }) if err != nil { panic(err) } @@ -225,7 +231,12 @@ func pipeWithTimeout(iceTimeout time.Duration, iceKeepalive time.Duration) (*Con aNotifier, aConnected := onConnected() bNotifier, bConnected := onConnected() - aAgent, err := NewAgent(&AgentConfig{Urls: urls, ConnectionTimeout: &iceTimeout, KeepaliveInterval: &iceKeepalive}) + aAgent, err := NewAgent(&AgentConfig{ + Urls: urls, + ConnectionTimeout: &iceTimeout, + KeepaliveInterval: &iceKeepalive, + NetworkTypes: supportedNetworkTypes, + }) if err != nil { panic(err) } @@ -234,7 +245,12 @@ func pipeWithTimeout(iceTimeout time.Duration, iceKeepalive time.Duration) (*Con panic(err) } - bAgent, err := NewAgent(&AgentConfig{Urls: urls, ConnectionTimeout: &iceTimeout, KeepaliveInterval: &iceKeepalive}) + bAgent, err := NewAgent(&AgentConfig{ + Urls: urls, + ConnectionTimeout: &iceTimeout, + KeepaliveInterval: &iceKeepalive, + NetworkTypes: supportedNetworkTypes, + }) if err != nil { panic(err) } diff --git a/util.go b/util.go index 0d9e91e..9de782a 100644 --- a/util.go +++ b/util.go @@ -5,12 +5,23 @@ import ( "sync/atomic" ) -func localInterfaces() (ips []net.IP) { +func localInterfaces(networkTypes []NetworkType) (ips []net.IP) { ifaces, err := net.Interfaces() if err != nil { return ips } + var IPv4Requested, IPv6Requested bool + for _, typ := range networkTypes { + if typ.IsIPv4() { + IPv4Requested = true + } + + if typ.IsIPv6() { + IPv6Requested = true + } + } + for _, iface := range ifaces { if iface.Flags&net.FlagUp == 0 { continue // interface down @@ -33,17 +44,18 @@ func localInterfaces() (ips []net.IP) { ip = addr.IP } - if ip == nil || ip.IsLoopback() { continue } - // The conditions of invalidation written below are defined in - // https://tools.ietf.org/html/rfc8445#section-5.1.1.1 if ipv4 := ip.To4(); ipv4 == nil { - if !isSupportedIPv6(ip) { + if !IPv6Requested { + continue + } else if !isSupportedIPv6(ip) { continue } + } else if !IPv4Requested { + continue } ips = append(ips, ip) @@ -62,6 +74,8 @@ func (a *atomicError) Load() error { return err.error } +// The conditions of invalidation written below are defined in +// https://tools.ietf.org/html/rfc8445#section-5.1.1.1 func isSupportedIPv6(ip net.IP) bool { if len(ip) != net.IPv6len || !isZeros(ip[0:12]) || // !(IPv4-compatible IPv6)