github.com/database64128/shadowsocks-go@v1.10.2-0.20240315062903-143a773533f1/conn/sockaddr_windows.go (about)

     1  package conn
     2  
     3  import (
     4  	"fmt"
     5  	"net/netip"
     6  	"unsafe"
     7  
     8  	"golang.org/x/sys/windows"
     9  )
    10  
    11  const (
    12  	SizeofSockaddrInet4 = uint32(unsafe.Sizeof(windows.RawSockaddrInet4{}))
    13  	SizeofSockaddrInet6 = uint32(unsafe.Sizeof(windows.RawSockaddrInet6{}))
    14  )
    15  
    16  func AddrPortToSockaddrValue(addrPort netip.AddrPort) (rsa6 windows.RawSockaddrInet6, namelen uint32) {
    17  	addr, port := addrPort.Addr(), addrPort.Port()
    18  	p := (*[2]byte)(unsafe.Pointer(&rsa6.Port))
    19  	p[0] = byte(port >> 8)
    20  	p[1] = byte(port)
    21  	if addr.Is4() {
    22  		rsa6.Family = windows.AF_INET
    23  		a := (*[4]byte)(unsafe.Pointer(&rsa6.Flowinfo))
    24  		*a = addr.As4()
    25  		namelen = SizeofSockaddrInet4
    26  		return
    27  	}
    28  	rsa6.Family = windows.AF_INET6
    29  	rsa6.Addr = addr.As16()
    30  	namelen = SizeofSockaddrInet6
    31  	return
    32  }
    33  
    34  func SockaddrValueToAddrPort(rsa6 windows.RawSockaddrInet6, namelen uint32) (netip.AddrPort, error) {
    35  	p := (*[2]byte)(unsafe.Pointer(&rsa6.Port))
    36  	port := uint16(p[0])<<8 + uint16(p[1])
    37  	var addr netip.Addr
    38  	switch namelen {
    39  	case SizeofSockaddrInet4:
    40  		addr = netip.AddrFrom4(*(*[4]byte)(unsafe.Pointer(&rsa6.Flowinfo)))
    41  	case SizeofSockaddrInet6:
    42  		addr = netip.AddrFrom16(rsa6.Addr)
    43  	default:
    44  		return netip.AddrPort{}, fmt.Errorf("bad sockaddr length: %d", namelen)
    45  	}
    46  	return netip.AddrPortFrom(addr, port), nil
    47  }
    48  
    49  func AddrPortToSockaddr(addrPort netip.AddrPort) (name *byte, namelen uint32) {
    50  	if addrPort.Addr().Is4() {
    51  		rsa4 := AddrPortToSockaddrInet4(addrPort)
    52  		name = (*byte)(unsafe.Pointer(&rsa4))
    53  		namelen = SizeofSockaddrInet4
    54  	} else {
    55  		rsa6 := AddrPortToSockaddrInet6(addrPort)
    56  		name = (*byte)(unsafe.Pointer(&rsa6))
    57  		namelen = SizeofSockaddrInet6
    58  	}
    59  	return
    60  }
    61  
    62  func AddrPortUnmappedToSockaddr(addrPort netip.AddrPort) (name *byte, namelen uint32) {
    63  	if addr := addrPort.Addr(); addr.Is4() || addr.Is4In6() {
    64  		rsa4 := AddrPortToSockaddrInet4(addrPort)
    65  		name = (*byte)(unsafe.Pointer(&rsa4))
    66  		namelen = SizeofSockaddrInet4
    67  	} else {
    68  		rsa6 := AddrPortToSockaddrInet6(addrPort)
    69  		name = (*byte)(unsafe.Pointer(&rsa6))
    70  		namelen = SizeofSockaddrInet6
    71  	}
    72  	return
    73  }
    74  
    75  func AddrPortToSockaddrInet4(addrPort netip.AddrPort) windows.RawSockaddrInet4 {
    76  	addr := addrPort.Addr()
    77  	port := addrPort.Port()
    78  	rsa4 := windows.RawSockaddrInet4{
    79  		Family: windows.AF_INET,
    80  		Addr:   addr.As4(),
    81  	}
    82  	p := (*[2]byte)(unsafe.Pointer(&rsa4.Port))
    83  	p[0] = byte(port >> 8)
    84  	p[1] = byte(port)
    85  	return rsa4
    86  }
    87  
    88  func AddrPortToSockaddrInet6(addrPort netip.AddrPort) windows.RawSockaddrInet6 {
    89  	addr := addrPort.Addr()
    90  	port := addrPort.Port()
    91  	rsa6 := windows.RawSockaddrInet6{
    92  		Family: windows.AF_INET6,
    93  		Addr:   addr.As16(),
    94  	}
    95  	p := (*[2]byte)(unsafe.Pointer(&rsa6.Port))
    96  	p[0] = byte(port >> 8)
    97  	p[1] = byte(port)
    98  	return rsa6
    99  }
   100  
   101  func SockaddrToAddrPort(name *byte, namelen uint32) (netip.AddrPort, error) {
   102  	switch namelen {
   103  	case SizeofSockaddrInet4:
   104  		rsa4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(name))
   105  		return SockaddrInet4ToAddrPort(rsa4), nil
   106  
   107  	case SizeofSockaddrInet6:
   108  		rsa6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(name))
   109  		return SockaddrInet6ToAddrPort(rsa6), nil
   110  
   111  	default:
   112  		return netip.AddrPort{}, fmt.Errorf("bad sockaddr length: %d", namelen)
   113  	}
   114  }
   115  
   116  func SockaddrInet4ToAddrPort(sa *windows.RawSockaddrInet4) netip.AddrPort {
   117  	portp := (*[2]byte)(unsafe.Pointer(&sa.Port))
   118  	port := uint16(portp[0])<<8 + uint16(portp[1])
   119  	ip := netip.AddrFrom4(sa.Addr)
   120  	return netip.AddrPortFrom(ip, port)
   121  }
   122  
   123  func SockaddrInet6ToAddrPort(sa *windows.RawSockaddrInet6) netip.AddrPort {
   124  	portp := (*[2]byte)(unsafe.Pointer(&sa.Port))
   125  	port := uint16(portp[0])<<8 + uint16(portp[1])
   126  	ip := netip.AddrFrom16(sa.Addr)
   127  	return netip.AddrPortFrom(ip, port)
   128  }