sockaddr.go 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package utp
  2. /*
  3. #include "utp.h"
  4. */
  5. import "C"
  6. import (
  7. "net"
  8. "strconv"
  9. "syscall"
  10. "unsafe"
  11. "github.com/anacrolix/missinggo/inproc"
  12. )
  13. func toSockaddrInet(ip net.IP, port int, zone string) (rsa syscall.RawSockaddrAny, len C.socklen_t) {
  14. if ip4 := ip.To4(); ip4 != nil && zone == "" {
  15. rsa4 := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&rsa))
  16. rsa4.Family = syscall.AF_INET
  17. rsa4.Port = uint16(port)
  18. if n := copy(rsa4.Addr[:], ip4); n != 4 {
  19. panic(n)
  20. }
  21. len = C.socklen_t(unsafe.Sizeof(*rsa4))
  22. return
  23. }
  24. rsa6 := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&rsa))
  25. rsa6.Family = syscall.AF_INET6
  26. rsa6.Scope_id = zoneToScopeId(zone)
  27. rsa6.Port = uint16(port)
  28. if ip != nil {
  29. if n := copy(rsa6.Addr[:], ip); n != 16 {
  30. panic(n)
  31. }
  32. }
  33. len = C.socklen_t(unsafe.Sizeof(*rsa6))
  34. return
  35. }
  36. func zoneToScopeId(zone string) uint32 {
  37. if zone == "" {
  38. return 0
  39. }
  40. if ifi, err := net.InterfaceByName(zone); err == nil {
  41. return uint32(ifi.Index)
  42. }
  43. ui64, _ := strconv.ParseUint(zone, 10, 32)
  44. return uint32(ui64)
  45. }
  46. func structSockaddrToUDPAddr(sa *C.struct_sockaddr, udp *net.UDPAddr) error {
  47. return anySockaddrToUdp((*syscall.RawSockaddrAny)(unsafe.Pointer(sa)), udp)
  48. }
  49. func anySockaddrToUdp(rsa *syscall.RawSockaddrAny, udp *net.UDPAddr) error {
  50. switch rsa.Addr.Family {
  51. case syscall.AF_INET:
  52. sa := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa))
  53. udp.Port = int(sa.Port)
  54. udp.IP = append(udp.IP[:0], sa.Addr[:]...)
  55. return nil
  56. case syscall.AF_INET6:
  57. sa := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa))
  58. udp.Port = int(sa.Port)
  59. udp.IP = append(udp.IP[:0], sa.Addr[:]...)
  60. return nil
  61. default:
  62. return syscall.EAFNOSUPPORT
  63. }
  64. }
  65. func sockaddrToUDP(sa syscall.Sockaddr) net.Addr {
  66. switch sa := sa.(type) {
  67. case *syscall.SockaddrInet4:
  68. return &net.UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
  69. case *syscall.SockaddrInet6:
  70. return &net.UDPAddr{IP: sa.Addr[0:], Port: sa.Port /*Zone: zoneToString(int(sa.ZoneId))*/}
  71. }
  72. return nil
  73. }
  74. func netAddrToLibSockaddr(na net.Addr) (rsa syscall.RawSockaddrAny, len C.socklen_t) {
  75. switch v := na.(type) {
  76. case *net.UDPAddr:
  77. return toSockaddrInet(v.IP, v.Port, v.Zone)
  78. case inproc.Addr:
  79. rsa6 := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&rsa))
  80. rsa6.Port = uint16(v.Port)
  81. len = C.socklen_t(unsafe.Sizeof(rsa))
  82. return
  83. default:
  84. panic(na)
  85. }
  86. }