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  }