ZeroTierOne/go/pkg/zerotier/endpoint.go

93 lines
2.5 KiB
Go

package zerotier
// #include "../../native/GoGlue.h"
import "C"
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"unsafe"
)
const (
EndpointTypeNil = C.ZT_ENDPOINT_TYPE_NIL
EndpointTypeZeroTier = C.ZT_ENDPOINT_TYPE_ZEROTIER
EndpointTypeEthernet = C.ZT_ENDPOINT_TYPE_ETHERNET
EndpointTypeWifiDirect = C.ZT_ENDPOINT_TYPE_WIFI_DIRECT
EndpointTypeBluetooth = C.ZT_ENDPOINT_TYPE_BLUETOOTH
EndpointTypeIp = C.ZT_ENDPOINT_TYPE_IP
EndpointTypeIpUdp = C.ZT_ENDPOINT_TYPE_IP_UDP
EndpointTypeIpTcp = C.ZT_ENDPOINT_TYPE_IP_TCP
EndpointTypeIpHttp2 = C.ZT_ENDPOINT_TYPE_IP_HTTP2
)
type Endpoint struct {
cep C.ZT_Endpoint
}
// Type returns this endpoint's type.
func (ep *Endpoint) Type() int {
return ep.cep._type
}
// InetAddress gets this Endpoint as an InetAddress or nil if its type is not addressed by one.
func (ep *Endpoint) InetAddress() *InetAddress {
switch ep.cep._type {
case EndpointTypeIp, EndpointTypeIpUdp, EndpointTypeIpTcp, EndpointTypeIpHttp2:
ua := sockaddrStorageToUDPAddr(&(ep.cep.a.ss))
return &InetAddress{IP: ua.IP, Port: ua.Port}
}
return nil
}
func (ep *Endpoint) String() string {
switch ep.cep._type {
case EndpointTypeZeroTier:
fp := Fingerprint{Address: Address(ep.cep.a.fp.address), Hash: *((*[48]byte)(unsafe.Pointer(&ep.cep.a.fp.hash[0])))}
return fmt.Sprintf("%d/%s", ep.Type(), fp.String())
case EndpointTypeEthernet, EndpointTypeWifiDirect, EndpointTypeBluetooth:
return fmt.Sprintf("%d/%s", ep.Type(), MAC(ep.cep.a.mac).String())
case EndpointTypeIp, EndpointTypeIpUdp, EndpointTypeIpTcp, EndpointTypeIpHttp2:
return fmt.Sprintf("%d/%s", ep.Type(), ep.InetAddress().String())
}
return fmt.Sprintf("%d", ep.Type())
}
func (ep *Endpoint) MarshalJSON() ([]byte, error) {
s := ep.String()
return json.Marshal(&s)
}
func (ep *Endpoint) UnmarshalJSON(j []byte) error {
var s string
err := json.Unmarshal(j, &s)
if err != nil {
return err
}
slashIdx := strings.IndexRune(s, '/')
if slashIdx < 0 {
ep.cep._type = C.uint(strconv.ParseUint(s, 10, 32))
} else if slashIdx == 0 || slashIdx >= (len(s)-1) {
return ErrInvalidParameter
} else {
ep.cep._type = C.uint(strconv.ParseUint(s[0:slashIdx], 10, 32))
s = s[slashIdx+1:]
}
switch ep.cep._type {
case EndpointTypeNil:
return nil
case EndpointTypeZeroTier:
fp, err := NewFingerprintFromString(s)
if err != nil {
return err
}
ep.cep.a.fp.address = C.uint64_t(fp.Address)
copy(((*[48]byte)(unsafe.Pointer(&ep.cep.a.fp.hash[0])))[:], fp.Hash[:])
return nil
}
return ErrInvalidParameter
}