Add a customization to control network types

- Fix an issue with ipv6 srflx candidates gathering.
- Add SetNetworkTypes config to SettingEngine to control what network
  types are allowed to be connected.

Resolves #460
This commit is contained in:
Konstantin Itskov
2019-03-12 21:36:52 -04:00
parent be2ef55e62
commit 052b3f98c6
4 changed files with 78 additions and 22 deletions
+10 -6
View File
@@ -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 {
+24 -2
View File
@@ -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) {
+25 -9
View File
@@ -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)
}
+19 -5
View File
@@ -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)