mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 08:57:26 +02:00
159 lines
3.6 KiB
Go
159 lines
3.6 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"
|
|
import "C"
|
|
|
|
import (
|
|
"encoding/json"
|
|
"runtime"
|
|
"unsafe"
|
|
)
|
|
|
|
type Locator struct {
|
|
Timestamp int64 `json:"timestamp"`
|
|
Fingerprint *Fingerprint `json:"fingerprint"`
|
|
Endpoints []Endpoint `json:"endpoints"`
|
|
cl unsafe.Pointer
|
|
}
|
|
|
|
func newLocatorFromCLocator(cl unsafe.Pointer, needFinalizer bool) (*Locator, error) {
|
|
loc := new(Locator)
|
|
loc.cl = cl
|
|
err := loc.init(needFinalizer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return loc, nil
|
|
}
|
|
|
|
func NewLocator(ts int64, endpoints []*Endpoint, signer *Identity) (*Locator, error) {
|
|
if ts <= 0 || len(endpoints) == 0 || signer == nil {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
eps := make([]C.ZT_Endpoint, 0, len(endpoints))
|
|
for _, e := range endpoints {
|
|
eps = append(eps, e.cep)
|
|
}
|
|
loc := C.ZT_Locator_create(C.int64_t(ts), &eps[0], nil, C.uint(len(eps)), signer.cIdentity())
|
|
if uintptr(loc) == 0 {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
|
|
goloc := new(Locator)
|
|
goloc.cl = unsafe.Pointer(loc)
|
|
return goloc, goloc.init(true)
|
|
}
|
|
|
|
func NewLocatorFromBytes(lb []byte) (*Locator, error) {
|
|
if len(lb) == 0 {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
loc := C.ZT_Locator_unmarshal(unsafe.Pointer(&lb[0]), C.uint(len(lb)))
|
|
if uintptr(loc) == 0 {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
|
|
goloc := new(Locator)
|
|
goloc.cl = unsafe.Pointer(loc)
|
|
return goloc, goloc.init(true)
|
|
}
|
|
|
|
func NewLocatorFromString(s string) (*Locator, error) {
|
|
if len(s) == 0 {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
sb := []byte(s)
|
|
sb = append(sb, 0)
|
|
loc := C.ZT_Locator_fromString((*C.char)(unsafe.Pointer(&sb[0])))
|
|
if loc == nil {
|
|
return nil, ErrInvalidParameter
|
|
}
|
|
|
|
goloc := new(Locator)
|
|
goloc.cl = unsafe.Pointer(loc)
|
|
return goloc, goloc.init(true)
|
|
}
|
|
|
|
func (loc *Locator) Validate(id *Identity) bool {
|
|
if id == nil {
|
|
return false
|
|
}
|
|
return C.ZT_Locator_verify(loc.cl, id.cIdentity()) != 0
|
|
}
|
|
|
|
func (loc *Locator) Bytes() []byte {
|
|
if loc.cl == nil {
|
|
return nil
|
|
}
|
|
var buf [16384]byte // larger than ZT_LOCATOR_MARSHAL_SIZE_MAX
|
|
bl := C.ZT_Locator_marshal(loc.cl, unsafe.Pointer(&buf[0]), 16384)
|
|
if bl <= 0 {
|
|
return nil
|
|
}
|
|
return buf[0:int(bl)]
|
|
}
|
|
|
|
func (loc *Locator) String() string {
|
|
if loc.cl == nil {
|
|
return ""
|
|
}
|
|
var buf [16384]C.char // 16384 == ZT_LOCATOR_STRING_SIZE_MAX
|
|
return C.GoString(C.ZT_Locator_toString(loc.cl, &buf[0], 16384))
|
|
}
|
|
|
|
func (loc *Locator) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(loc)
|
|
}
|
|
|
|
func (loc *Locator) UnmarshalJSON(j []byte) error {
|
|
if loc.cl != nil {
|
|
C.ZT_Locator_delete(loc.cl)
|
|
loc.cl = unsafe.Pointer(nil)
|
|
}
|
|
|
|
err := json.Unmarshal(j, loc)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return loc.init(true)
|
|
}
|
|
|
|
func locatorFinalizer(obj interface{}) {
|
|
if obj != nil {
|
|
cl := obj.(*Locator).cl
|
|
if cl != nil {
|
|
C.ZT_Locator_delete(cl)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (loc *Locator) init(needFinalizer bool) error {
|
|
loc.Timestamp = int64(C.ZT_Locator_timestamp(loc.cl))
|
|
cfp := C.ZT_Locator_fingerprint(loc.cl)
|
|
if uintptr(unsafe.Pointer(cfp)) == 0 {
|
|
return ErrInternal
|
|
}
|
|
loc.Fingerprint = newFingerprintFromCFingerprint(cfp)
|
|
epc := int(C.ZT_Locator_endpointCount(loc.cl))
|
|
loc.Endpoints = make([]Endpoint, epc)
|
|
for i := 0; i < epc; i++ {
|
|
loc.Endpoints[i].cep = *C.ZT_Locator_endpoint(loc.cl, C.uint(i))
|
|
}
|
|
if needFinalizer {
|
|
runtime.SetFinalizer(loc, locatorFinalizer)
|
|
}
|
|
return nil
|
|
}
|