package utp /* #include "utp.h" */ import "C" import ( "net" "strconv" "syscall" "github.com/anacrolix/missinggo/inproc" "unsafe" ) func toSockaddrInet(ip net.IP, port int, zone string) (*C.struct_sockaddr, C.socklen_t) { if ip4 := ip.To4(); ip4 != nil && zone == "" { rsa := syscall.RawSockaddrInet4{ // Len: syscall.SizeofSockaddrInet4, Family: syscall.AF_INET, Port: uint16(port), } if n := copy(rsa.Addr[:], ip4); n != 4 { panic(n) } return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa)) } rsa := syscall.RawSockaddrInet6{ // Len: syscall.SizeofSockaddrInet6, Family: syscall.AF_INET6, Scope_id: zoneToScopeId(zone), Port: uint16(port), } if n := copy(rsa.Addr[:], ip); n != 16 { panic(n) } return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa)) } 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) *net.UDPAddr { meh, err := anyToSockaddr((*syscall.RawSockaddrAny)(unsafe.Pointer(sa))) if err != nil { panic(err) } return sockaddrToUDP(meh).(*net.UDPAddr) } func anyToSockaddr(rsa *syscall.RawSockaddrAny) (syscall.Sockaddr, error) { // log.Printf("anyToSockaddr %#v", rsa) switch rsa.Addr.Family { case syscall.AF_INET: pp := (*syscall.RawSockaddrInet4)(unsafe.Pointer(rsa)) sa := new(syscall.SockaddrInet4) // p := (*[2]byte)(unsafe.Pointer(&pp.Port)) // sa.Port = int(p[0])<<8 + int(p[1]) // I don't know why the port isn't reversed when it comes from utp. sa.Port = int(pp.Port) for i := 0; i < len(sa.Addr); i++ { sa.Addr[i] = pp.Addr[i] } return sa, nil case syscall.AF_INET6: pp := (*syscall.RawSockaddrInet6)(unsafe.Pointer(rsa)) sa := new(syscall.SockaddrInet6) // p := (*[2]byte)(unsafe.Pointer(&pp.Port)) // sa.Port = int(p[0])<<8 + int(p[1]) // I don't know why the port isn't reversed when it comes from utp. sa.Port = int(pp.Port) sa.ZoneId = pp.Scope_id for i := 0; i < len(sa.Addr); i++ { sa.Addr[i] = pp.Addr[i] } return sa, nil } return nil, 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) (*C.struct_sockaddr, C.socklen_t) { switch v := na.(type) { case *net.UDPAddr: return toSockaddrInet(v.IP, v.Port, v.Zone) case inproc.Addr: rsa := syscall.RawSockaddrInet6{ Port: uint16(v.Port), } return (*C.struct_sockaddr)(unsafe.Pointer(&rsa)), C.socklen_t(unsafe.Sizeof(rsa)) default: panic(na) } }