package ice
import (
"fmt"
"net"
"net/netip"
)
func addrWithOptionalZone(addr netip .Addr , zone string ) netip .Addr {
if zone == "" {
return addr
}
if addr .Is6 () && (addr .IsLinkLocalUnicast () || addr .IsLinkLocalMulticast ()) {
return addr .WithZone (zone )
}
return addr
}
func parseAddrFromIface(in net .Addr , ifcName string ) (netip .Addr , int , NetworkType , error ) {
addr , port , nt , err := parseAddr (in )
if err != nil {
return netip .Addr {}, 0 , 0 , err
}
if _ , ok := in .(*net .IPNet ); ok {
addr = addrWithOptionalZone (addr , ifcName )
}
return addr , port , nt , nil
}
func parseAddr(in net .Addr ) (netip .Addr , int , NetworkType , error ) {
switch addr := in .(type ) {
case *net .IPNet :
ipAddr , err := ipAddrToNetIP (addr .IP , "" )
if err != nil {
return netip .Addr {}, 0 , 0 , err
}
return ipAddr , 0 , 0 , nil
case *net .IPAddr :
ipAddr , err := ipAddrToNetIP (addr .IP , addr .Zone )
if err != nil {
return netip .Addr {}, 0 , 0 , err
}
return ipAddr , 0 , 0 , nil
case *net .UDPAddr :
ipAddr , err := ipAddrToNetIP (addr .IP , addr .Zone )
if err != nil {
return netip .Addr {}, 0 , 0 , err
}
var nt NetworkType
if ipAddr .Is4 () {
nt = NetworkTypeUDP4
} else {
nt = NetworkTypeUDP6
}
return ipAddr , addr .Port , nt , nil
case *net .TCPAddr :
ipAddr , err := ipAddrToNetIP (addr .IP , addr .Zone )
if err != nil {
return netip .Addr {}, 0 , 0 , err
}
var nt NetworkType
if ipAddr .Is4 () {
nt = NetworkTypeTCP4
} else {
nt = NetworkTypeTCP6
}
return ipAddr , addr .Port , nt , nil
default :
return netip .Addr {}, 0 , 0 , addrParseError {in }
}
}
type addrParseError struct {
addr net .Addr
}
func (e addrParseError ) Error () string {
return fmt .Sprintf ("do not know how to parse address type %T" , e .addr )
}
type ipConvertError struct {
ip []byte
}
func (e ipConvertError ) Error () string {
return fmt .Sprintf ("failed to convert IP '%s' to netip.Addr" , e .ip )
}
func ipAddrToNetIP(ip []byte , zone string ) (netip .Addr , error ) {
netIPAddr , ok := netip .AddrFromSlice (ip )
if !ok {
return netip .Addr {}, ipConvertError {ip }
}
netIPAddr = netIPAddr .Unmap ()
netIPAddr = addrWithOptionalZone (netIPAddr , zone )
return netIPAddr , nil
}
func createAddr(network NetworkType , ip netip .Addr , port int ) net .Addr {
switch {
case network .IsTCP ():
return &net .TCPAddr {IP : ip .AsSlice (), Port : port , Zone : ip .Zone ()}
default :
return &net .UDPAddr {IP : ip .AsSlice (), Port : port , Zone : ip .Zone ()}
}
}
func addrEqual(a , b net .Addr ) bool {
aIP , aPort , aType , aErr := parseAddr (a )
if aErr != nil {
return false
}
bIP , bPort , bType , bErr := parseAddr (b )
if bErr != nil {
return false
}
return aType == bType && aIP .Compare (bIP ) == 0 && aPort == bPort
}
type AddrPort [18 ]byte
func toAddrPort(addr net .Addr ) AddrPort {
var ap AddrPort
switch addr := addr .(type ) {
case *net .UDPAddr :
copy (ap [:16 ], addr .IP .To16 ())
ap [16 ] = uint8 (addr .Port >> 8 )
ap [17 ] = uint8 (addr .Port )
case *net .TCPAddr :
copy (ap [:16 ], addr .IP .To16 ())
ap [16 ] = uint8 (addr .Port >> 8 )
ap [17 ] = uint8 (addr .Port )
}
return ap
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .