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