Skip to content

Commit

Permalink
IPv6 relay support
Browse files Browse the repository at this point in the history
  • Loading branch information
hetelek committed Jun 4, 2022
1 parent d14cb7e commit a1467ba
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 12 deletions.
55 changes: 43 additions & 12 deletions gather.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ func (a *Agent) gatherCandidatesSrflxUDPMux(ctx context.Context, urls []*URL, ne
go func(url URL, network string, isIPv6 bool) {
defer wg.Done()

hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port)
hostPort := url.HostPortString()
serverAddr, err := a.net.ResolveUDPAddr(network, hostPort)
if err != nil {
a.log.Warnf("failed to resolve stun host: %s: %v", hostPort, err)
Expand Down Expand Up @@ -444,7 +444,7 @@ func (a *Agent) gatherCandidatesSrflx(ctx context.Context, urls []*URL, networkT
go func(url URL, network string) {
defer wg.Done()

hostPort := fmt.Sprintf("%s:%d", url.Host, url.Port)
hostPort := url.HostPortString()
serverAddr, err := a.net.ResolveUDPAddr(network, hostPort)
if err != nil {
a.log.Warnf("failed to resolve stun host: %s: %v", hostPort, err)
Expand Down Expand Up @@ -508,7 +508,6 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
var wg sync.WaitGroup
defer wg.Wait()

network := NetworkTypeUDP4.String()
for i := range urls {
switch {
case urls[i].Scheme != SchemeTypeTURN && urls[i].Scheme != SchemeTypeTURNS:
Expand All @@ -521,21 +520,38 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
return
}

wg.Add(1)
go func(url URL) {
generateCandidate := func(url URL, ipv6 bool) {
defer wg.Done()
TURNServerAddr := fmt.Sprintf("%s:%d", url.Host, url.Port)

var (
TURNServerAddr = url.HostPortString()

udpNetworkType string
tcpNetworkType string
localAddress string
network string

locConn net.PacketConn
err error
RelAddr string
RelPort int
relayProtocol string
)

if ipv6 {
udpNetworkType = NetworkTypeUDP6.String()
tcpNetworkType = NetworkTypeTCP6.String()
localAddress = ":"
} else {
udpNetworkType = NetworkTypeUDP4.String()
tcpNetworkType = NetworkTypeTCP4.String()
localAddress = "0.0.0.0:0"
}

switch {
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURN:
if locConn, err = a.net.ListenPacket(network, "0.0.0.0:0"); err != nil {
network = udpNetworkType
if locConn, err = a.net.ListenPacket(network, localAddress); err != nil {
a.log.Warnf("Failed to listen %s: %v", network, err)
return
}
Expand All @@ -545,7 +561,8 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relayProtocol = udp
case a.proxyDialer != nil && url.Proto == ProtoTypeTCP &&
(url.Scheme == SchemeTypeTURN || url.Scheme == SchemeTypeTURNS):
conn, connectErr := a.proxyDialer.Dial(NetworkTypeTCP4.String(), TURNServerAddr)
network = tcpNetworkType
conn, connectErr := a.proxyDialer.Dial(network, TURNServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to Dial TCP Addr %s via proxy dialer: %v", TURNServerAddr, connectErr)
return
Expand All @@ -561,13 +578,14 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
locConn = turn.NewSTUNConn(conn)

case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURN:
tcpAddr, connectErr := net.ResolveTCPAddr(NetworkTypeTCP4.String(), TURNServerAddr)
network = tcpNetworkType
tcpAddr, connectErr := net.ResolveTCPAddr(network, TURNServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to resolve TCP Addr %s: %v", TURNServerAddr, connectErr)
return
}

conn, connectErr := net.DialTCP(NetworkTypeTCP4.String(), nil, tcpAddr)
conn, connectErr := net.DialTCP(network, nil, tcpAddr)
if connectErr != nil {
a.log.Warnf("Failed to Dial TCP Addr %s: %v", TURNServerAddr, connectErr)
return
Expand All @@ -578,6 +596,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relayProtocol = tcp
locConn = turn.NewSTUNConn(conn)
case url.Proto == ProtoTypeUDP && url.Scheme == SchemeTypeTURNS:
network = udpNetworkType
udpAddr, connectErr := net.ResolveUDPAddr(network, TURNServerAddr)
if connectErr != nil {
a.log.Warnf("Failed to resolve UDP Addr %s: %v", TURNServerAddr, connectErr)
Expand All @@ -598,7 +617,8 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
relayProtocol = "dtls"
locConn = &fakePacketConn{conn}
case url.Proto == ProtoTypeTCP && url.Scheme == SchemeTypeTURNS:
conn, connectErr := tls.Dial(NetworkTypeTCP4.String(), TURNServerAddr, &tls.Config{
network = tcpNetworkType
conn, connectErr := tls.Dial(network, TURNServerAddr, &tls.Config{
InsecureSkipVerify: a.insecureSkipVerify, //nolint:gosec
})
if connectErr != nil {
Expand All @@ -621,6 +641,7 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
Password: url.Password,
LoggerFactory: a.loggerFactory,
Net: a.net,
IPv6: ipv6,
})
if err != nil {
closeConnAndLog(locConn, a.log, fmt.Sprintf("Failed to build new turn.Client %s %s", TURNServerAddr, err))
Expand Down Expand Up @@ -676,6 +697,16 @@ func (a *Agent) gatherCandidatesRelay(ctx context.Context, urls []*URL) { //noli
}
a.log.Warnf("Failed to append to localCandidates and run onCandidateHdlr: %v", err)
}
}(*urls[i])
}

url := *urls[i]

// ipv4
wg.Add(1)
go generateCandidate(url, false)

// ipv6
wg.Add(1)
go generateCandidate(url, true)
}
}
6 changes: 6 additions & 0 deletions url.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ func parseProto(raw string) (ProtoType, error) {
return proto, nil
}

// HostPortString returns a string in the format "host:port" or "[host]:port" if
// a literal IPv6 address is given
func (u URL) HostPortString() string {
return net.JoinHostPort(u.Host, strconv.Itoa(u.Port))
}

func (u URL) String() string {
rawURL := u.Scheme.String() + ":" + net.JoinHostPort(u.Host, strconv.Itoa(u.Port))
if u.Scheme == SchemeTypeTURN || u.Scheme == SchemeTypeTURNS {
Expand Down

0 comments on commit a1467ba

Please sign in to comment.