Skip to content

Commit

Permalink
Merge d8dbdf2 into b31effa
Browse files Browse the repository at this point in the history
  • Loading branch information
trivigy committed Mar 13, 2019
2 parents b31effa + d8dbdf2 commit f5ce902
Show file tree
Hide file tree
Showing 9 changed files with 219 additions and 24 deletions.
11 changes: 10 additions & 1 deletion icegatherer.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type ICEGatherer struct {
// This constructor is part of the ORTC API. It is not
// meant to be used together with the basic WebRTC API.
func (api *API) NewICEGatherer(opts ICEGatherOptions) (*ICEGatherer, error) {
validatedServers := []*ice.URL{}
var validatedServers []*ice.URL
if len(opts.ICEServers) > 0 {
for _, server := range opts.ICEServers {
url, err := server.validate()
Expand Down Expand Up @@ -64,6 +64,15 @@ func (g *ICEGatherer) Gather() error {
KeepaliveInterval: g.api.settingEngine.timeout.ICEKeepalive,
}

requestedNetworkTypes := g.api.settingEngine.candidates.ICENetworkTypes
if len(requestedNetworkTypes) == 0 {
requestedNetworkTypes = supportedNetworkTypes
}

for _, typ := range requestedNetworkTypes {
config.NetworkTypes = append(config.NetworkTypes, ice.NetworkType(typ))
}

agent, err := ice.NewAgent(config)
if err != nil {
return err
Expand Down
16 changes: 10 additions & 6 deletions internal/ice/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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})
Expand All @@ -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 {
Expand Down
26 changes: 24 additions & 2 deletions internal/ice/networktype.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)

Expand Down Expand Up @@ -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) {
Expand Down
34 changes: 25 additions & 9 deletions internal/ice/transport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand All @@ -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)
}

Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down
24 changes: 19 additions & 5 deletions internal/ice/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down
67 changes: 67 additions & 0 deletions networktype.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package webrtc

import (
"fmt"
)

var supportedNetworkTypes = []NetworkType{
NetworkTypeUDP4,
NetworkTypeUDP6,
// NetworkTypeTCP4, // Not supported yet
// NetworkTypeTCP6, // Not supported yet
}

// NetworkType represents the type of network
type NetworkType int

const (
// NetworkTypeUDP4 indicates UDP over IPv4.
NetworkTypeUDP4 NetworkType = iota + 1

// NetworkTypeUDP6 indicates UDP over IPv6.
NetworkTypeUDP6

// NetworkTypeTCP4 indicates TCP over IPv4.
NetworkTypeTCP4

// NetworkTypeTCP6 indicates TCP over IPv6.
NetworkTypeTCP6
)

// This is done this way because of a linter.
const (
networkTypeUDP4Str = "udp4"
networkTypeUDP6Str = "udp6"
networkTypeTCP4Str = "tcp4"
networkTypeTCP6Str = "tcp6"
)

func (t NetworkType) String() string {
switch t {
case NetworkTypeUDP4:
return networkTypeUDP4Str
case NetworkTypeUDP6:
return networkTypeUDP6Str
case NetworkTypeTCP4:
return networkTypeTCP4Str
case NetworkTypeTCP6:
return networkTypeTCP6Str
default:
return ErrUnknownType.Error()
}
}

func newNetworkType(raw string) (NetworkType, error) {
switch raw {
case networkTypeUDP4Str:
return NetworkTypeUDP4, nil
case networkTypeUDP6Str:
return NetworkTypeUDP6, nil
case networkTypeTCP4Str:
return NetworkTypeTCP4, nil
case networkTypeTCP6Str:
return NetworkTypeTCP6, nil
default:
return NetworkType(Unknown), fmt.Errorf("unknown network type: %s", raw)
}
}
54 changes: 54 additions & 0 deletions networktype_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package webrtc

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestNetworkType_String(t *testing.T) {
testCases := []struct {
cType NetworkType
expectedString string
}{
{NetworkType(Unknown), unknownStr},
{NetworkTypeUDP4, "udp4"},
{NetworkTypeUDP6, "udp6"},
{NetworkTypeTCP4, "tcp4"},
{NetworkTypeTCP6, "tcp6"},
}

for i, testCase := range testCases {
assert.Equal(t,
testCase.expectedString,
testCase.cType.String(),
"testCase: %d %v", i, testCase,
)
}
}

func TestNetworkType(t *testing.T) {
testCases := []struct {
typeString string
shouldFail bool
expectedType NetworkType
}{
{unknownStr, true, NetworkType(Unknown)},
{"udp4", false, NetworkTypeUDP4},
{"udp6", false, NetworkTypeUDP6},
{"tcp4", false, NetworkTypeTCP4},
{"tcp6", false, NetworkTypeTCP6},
}

for i, testCase := range testCases {
actual, err := newNetworkType(testCase.typeString)
if (err != nil) != testCase.shouldFail {
t.Error(err)
}
assert.Equal(t,
testCase.expectedType,
actual,
"testCase: %d %v", i, testCase,
)
}
}

0 comments on commit f5ce902

Please sign in to comment.