github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/internal/netpoll/socktoaddr.go (about) 1 // +build linux darwin netbsd freebsd openbsd dragonfly 2 3 package netpoll 4 5 import ( 6 nt "net" 7 8 "golang.org/x/sys/unix" 9 ) 10 11 // SockaddrToTCPOrUnixAddr converts a Sockaddr to a net.TCPAddr or net.UnixAddr. 12 // Returns nil if conversion fails. 13 func SockaddrToTCPOrUnixAddr(sa interface{}) nt.Addr { 14 switch sa := sa.(type) { 15 case *unix.SockaddrInet4: 16 ip := sockaddrInet4ToIP(sa) 17 return &nt.TCPAddr{IP: ip, Port: sa.Port} 18 case *unix.SockaddrInet6: 19 ip, zone := sockaddrInet6ToIPAndZone(sa) 20 return &nt.TCPAddr{IP: ip, Port: sa.Port, Zone: zone} 21 case *unix.SockaddrUnix: 22 return &nt.UnixAddr{Name: sa.Name, Net: "unix"} 23 } 24 return nil 25 } 26 27 // SockaddrToUDPAddr converts a Sockaddr to a net.UDPAddr 28 // Returns nil if conversion fails. 29 func SockaddrToUDPAddr(sa interface{}) *nt.UDPAddr { 30 switch sa := sa.(type) { 31 case *unix.SockaddrInet4: 32 ip := sockaddrInet4ToIP(sa) 33 return &nt.UDPAddr{IP: ip, Port: sa.Port} 34 case *unix.SockaddrInet6: 35 ip, zone := sockaddrInet6ToIPAndZone(sa) 36 return &nt.UDPAddr{IP: ip, Port: sa.Port, Zone: zone} 37 } 38 return nil 39 } 40 41 // sockaddrInet4ToIPAndZone converts a SockaddrInet4 to a net.IP. 42 // It returns nil if conversion fails. 43 func sockaddrInet4ToIP(sa *unix.SockaddrInet4) nt.IP { 44 ip := make([]byte, 16) 45 // V4InV6Prefix 46 ip[10] = 0xff 47 ip[11] = 0xff 48 copy(ip[12:16], sa.Addr[:]) 49 return ip 50 } 51 52 // sockaddrInet6ToIPAndZone converts a SockaddrInet6 to a net.IP with IPv6 Zone. 53 // It returns nil if conversion fails. 54 func sockaddrInet6ToIPAndZone(sa *unix.SockaddrInet6) (nt.IP, string) { 55 ip := make([]byte, 16) 56 copy(ip, sa.Addr[:]) 57 return ip, ip6ZoneToString(int(sa.ZoneId)) 58 } 59 60 // ip6ZoneToString converts an IP6 Zone unix int to a net string 61 // returns "" if zone is 0 62 func ip6ZoneToString(zone int) string { 63 if zone == 0 { 64 return "" 65 } 66 if ifi, err := nt.InterfaceByIndex(zone); err == nil { 67 return ifi.Name 68 } 69 return int2decimal(uint(zone)) 70 } 71 72 // Convert int to decimal string. 73 func int2decimal(i uint) string { 74 if i == 0 { 75 return "0" 76 } 77 78 // Assemble decimal in reverse order. 79 var b [32]byte 80 bp := len(b) 81 for ; i > 0; i /= 10 { 82 bp-- 83 b[bp] = byte(i%10) + '0' 84 } 85 return string(b[bp:]) 86 }