mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 08:57:26 +02:00
178 lines
4.8 KiB
Go
178 lines
4.8 KiB
Go
/*
|
|
* Copyright (C)2013-2020 ZeroTier, Inc.
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file in the project's root directory.
|
|
*
|
|
* Change Date: 2026-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2.0 of the Apache License.
|
|
*/
|
|
/****/
|
|
|
|
package zerotier
|
|
|
|
// #include "../../serviceiocore/GoGlue.h"
|
|
// const ZT_Fingerprint *_getFP(const ZT_Endpoint *ep) { return &(ep->value.fp); }
|
|
// uint64_t _getAddress(const ZT_Endpoint *ep) { return ep->value.fp.address; }
|
|
// uint64_t _getMAC(const ZT_Endpoint *ep) { return ep->value.mac; }
|
|
// const struct sockaddr_storage *_getSS(const ZT_Endpoint *ep) { return &(ep->value.ss); }
|
|
// void _setSS(ZT_Endpoint *ep,const void *ss) { memcpy(&(ep->value.ss),ss,sizeof(struct sockaddr_storage)); }
|
|
import "C"
|
|
|
|
import (
|
|
"encoding/json"
|
|
"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
|
|
EndpointTypeIpHttp = C.ZT_ENDPOINT_TYPE_IP_HTTP
|
|
)
|
|
|
|
type Endpoint struct {
|
|
cep C.ZT_Endpoint
|
|
}
|
|
|
|
func EndpointTypeToString(t int) string {
|
|
switch t {
|
|
case EndpointTypeZeroTier:
|
|
return "zerotier"
|
|
case EndpointTypeEthernet:
|
|
return "ethernet"
|
|
case EndpointTypeWifiDirect:
|
|
return "wifi-direct"
|
|
case EndpointTypeBluetooth:
|
|
return "bluetooth"
|
|
case EndpointTypeIp:
|
|
return "ip/raw"
|
|
case EndpointTypeIpUdp:
|
|
return "ip/udp"
|
|
case EndpointTypeIpTcp:
|
|
return "ip/tcp"
|
|
case EndpointTypeIpHttp:
|
|
return "ip/http"
|
|
}
|
|
return "unsupported"
|
|
}
|
|
|
|
// NewEndpointFromString constructs a new endpoint from an InetAddress or Endpoint string.
|
|
// This will auto detect whether this is a plain InetAddress or an Endpoint in string
|
|
// format. If the former it's created as a ZT_ENDPOINT_TYPE_IP_UDP endpoint.
|
|
func NewEndpointFromString(s string) (*Endpoint, error) {
|
|
if len(s) == 0 {
|
|
var ep Endpoint
|
|
ep.cep._type = C.ZT_ENDPOINT_TYPE_NIL
|
|
return &ep, nil
|
|
}
|
|
var ep Endpoint
|
|
cs := C.CString(s)
|
|
defer C.free(unsafe.Pointer(cs))
|
|
if C.ZT_Endpoint_fromString(&ep.cep, cs) != 0 {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
return &ep, nil
|
|
}
|
|
|
|
func NewEndpointFromInetAddress(addr *InetAddress) (*Endpoint, error) {
|
|
var ep Endpoint
|
|
var ss C.struct_sockaddr_storage
|
|
if !makeSockaddrStorage(addr.IP, addr.Port, &ss) {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
ep.cep._type = C.ZT_ENDPOINT_TYPE_IP_UDP
|
|
C._setSS(&ep.cep, unsafe.Pointer(&ss))
|
|
return &ep, nil
|
|
}
|
|
|
|
// Type returns this endpoint's type.
|
|
func (ep *Endpoint) Type() int {
|
|
return int(ep.cep._type)
|
|
}
|
|
|
|
// TypeString returns a human-readable endpoint type.
|
|
func (ep *Endpoint) TypeString() string {
|
|
return EndpointTypeToString(int(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, EndpointTypeIpHttp:
|
|
ua := sockaddrStorageToUDPAddr(C._getSS(&ep.cep))
|
|
return &InetAddress{IP: ua.IP, Port: ua.Port}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Address returns a ZeroTier address if this is a ZeroTier endpoint or a zero address otherwise.
|
|
func (ep *Endpoint) Address() Address {
|
|
switch ep.cep._type {
|
|
case EndpointTypeZeroTier:
|
|
return Address(C._getAddress(&ep.cep))
|
|
}
|
|
return Address(0)
|
|
}
|
|
|
|
// Fingerprint returns a fingerprint if this is a ZeroTier endpoint or nil otherwise.
|
|
func (ep *Endpoint) Fingerprint() *Fingerprint {
|
|
switch ep.cep._type {
|
|
case EndpointTypeZeroTier:
|
|
cfp := C._getFP(&ep.cep)
|
|
fp := Fingerprint{Address: Address(cfp.address), Hash: C.GoBytes(unsafe.Pointer(&cfp.hash[0]), 48)}
|
|
if allZero(fp.Hash) {
|
|
fp.Hash = nil
|
|
}
|
|
return &fp
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// MAC returns a MAC address if this is an Ethernet type endpoint or a zero address otherwise.
|
|
func (ep *Endpoint) MAC() MAC {
|
|
switch ep.cep._type {
|
|
case EndpointTypeEthernet, EndpointTypeWifiDirect, EndpointTypeBluetooth:
|
|
return MAC(C._getMAC(&ep.cep))
|
|
}
|
|
return MAC(0)
|
|
}
|
|
|
|
func (ep *Endpoint) String() string {
|
|
var buf [4096]byte
|
|
cs := C.ZT_Endpoint_toString(&ep.cep, (*C.char)(unsafe.Pointer(&buf[0])), 4096)
|
|
if cs == nil {
|
|
return "0"
|
|
}
|
|
return C.GoString(cs)
|
|
}
|
|
|
|
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
|
|
}
|
|
ep2, err := NewEndpointFromString(s)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*ep = *ep2
|
|
return nil
|
|
}
|
|
|
|
func (ep *Endpoint) setFromCEndpoint(cp *C.ZT_Endpoint) {
|
|
ep.cep = *cp
|
|
}
|