mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-06 12:33:44 +02:00
A bunch of go fixes, wire up root add/delete.
This commit is contained in:
parent
964c235ecf
commit
caad356b93
11 changed files with 134 additions and 89 deletions
|
@ -92,7 +92,7 @@ struct ZT_GoNode_Impl
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string defaultHomePath(OSUtils::platformDefaultHomePath());
|
static const std::string defaultHomePath(OSUtils::platformDefaultHomePath());
|
||||||
const char *ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str();
|
const char *const ZT_PLATFORM_DEFAULT_HOMEPATH = defaultHomePath.c_str();
|
||||||
|
|
||||||
// These are implemented in Go code.
|
// These are implemented in Go code.
|
||||||
extern "C" int goPathCheckFunc(void *,const ZT_Identity *,int,const void *,int);
|
extern "C" int goPathCheckFunc(void *,const ZT_Identity *,int,const void *,int);
|
||||||
|
@ -300,6 +300,7 @@ extern "C" ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
struct ZT_Node_Callbacks cb;
|
struct ZT_Node_Callbacks cb;
|
||||||
|
|
||||||
cb.statePutFunction = &ZT_GoNode_StatePutFunction;
|
cb.statePutFunction = &ZT_GoNode_StatePutFunction;
|
||||||
cb.stateGetFunction = &ZT_GoNode_StateGetFunction;
|
cb.stateGetFunction = &ZT_GoNode_StateGetFunction;
|
||||||
cb.wirePacketSendFunction = &ZT_GoNode_WirePacketSendFunction;
|
cb.wirePacketSendFunction = &ZT_GoNode_WirePacketSendFunction;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "../../include/ZeroTierCore.h"
|
#include "../../include/ZeroTierCore.h"
|
||||||
#include "../../node/Constants.hpp"
|
#include "../../node/Constants.hpp"
|
||||||
|
@ -29,7 +30,7 @@ typedef void ZT_GoTap;
|
||||||
struct ZT_GoNode_Impl;
|
struct ZT_GoNode_Impl;
|
||||||
typedef struct ZT_GoNode_Impl ZT_GoNode;
|
typedef struct ZT_GoNode_Impl ZT_GoNode;
|
||||||
|
|
||||||
extern const char *ZT_PLATFORM_DEFAULT_HOMEPATH;
|
extern const char *const ZT_PLATFORM_DEFAULT_HOMEPATH;
|
||||||
|
|
||||||
ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr);
|
ZT_GoNode *ZT_GoNode_new(const char *workingPath,uintptr_t userPtr);
|
||||||
void ZT_GoNode_delete(ZT_GoNode *gn);
|
void ZT_GoNode_delete(ZT_GoNode *gn);
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
secrand "crypto/rand"
|
secrand "crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -33,8 +34,6 @@ import (
|
||||||
// APISocketName is the default socket name for accessing the API
|
// APISocketName is the default socket name for accessing the API
|
||||||
const APISocketName = "apisocket"
|
const APISocketName = "apisocket"
|
||||||
|
|
||||||
var startTime = TimeMs()
|
|
||||||
|
|
||||||
// APIGet makes a query to the API via a Unix domain or windows pipe socket
|
// APIGet makes a query to the API via a Unix domain or windows pipe socket
|
||||||
func APIGet(basePath, socketName, authToken, queryPath string, obj interface{}) (int, int64, error) {
|
func APIGet(basePath, socketName, authToken, queryPath string, obj interface{}) (int, int64, error) {
|
||||||
client, err := createNamedSocketHTTPClient(basePath, socketName)
|
client, err := createNamedSocketHTTPClient(basePath, socketName)
|
||||||
|
@ -128,7 +127,7 @@ type APIStatus struct {
|
||||||
Address Address `json:"address"`
|
Address Address `json:"address"`
|
||||||
Clock int64 `json:"clock"`
|
Clock int64 `json:"clock"`
|
||||||
StartupTime int64 `json:"startupTime"`
|
StartupTime int64 `json:"startupTime"`
|
||||||
Config LocalConfig `json:"config"`
|
Config *LocalConfig `json:"config"`
|
||||||
Online bool `json:"online"`
|
Online bool `json:"online"`
|
||||||
PeerCount int `json:"peerCount"`
|
PeerCount int `json:"peerCount"`
|
||||||
PathCount int `json:"pathCount"`
|
PathCount int `json:"pathCount"`
|
||||||
|
@ -254,8 +253,6 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
|
|
||||||
smux := http.NewServeMux()
|
smux := http.NewServeMux()
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
smux.HandleFunc("/status", func(out http.ResponseWriter, req *http.Request) {
|
smux.HandleFunc("/status", func(out http.ResponseWriter, req *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
e := recover()
|
e := recover()
|
||||||
|
@ -278,7 +275,7 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
_ = apiSendObj(out, req, http.StatusOK, &APIStatus{
|
_ = apiSendObj(out, req, http.StatusOK, &APIStatus{
|
||||||
Address: node.Address(),
|
Address: node.Address(),
|
||||||
Clock: TimeMs(),
|
Clock: TimeMs(),
|
||||||
StartupTime: startTime,
|
StartupTime: node.startupTime,
|
||||||
Config: node.LocalConfig(),
|
Config: node.LocalConfig(),
|
||||||
Online: node.Online(),
|
Online: node.Online(),
|
||||||
PeerCount: len(peers),
|
PeerCount: len(peers),
|
||||||
|
@ -302,8 +299,6 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
smux.HandleFunc("/config", func(out http.ResponseWriter, req *http.Request) {
|
smux.HandleFunc("/config", func(out http.ResponseWriter, req *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
e := recover()
|
e := recover()
|
||||||
|
@ -336,9 +331,9 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
smux.HandleFunc("/peer/", func(out http.ResponseWriter, req *http.Request) {
|
smux.HandleFunc("/peer/", func(out http.ResponseWriter, req *http.Request) {
|
||||||
|
var err error
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
e := recover()
|
e := recover()
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
@ -351,65 +346,92 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
}
|
}
|
||||||
apiSetStandardHeaders(out)
|
apiSetStandardHeaders(out)
|
||||||
|
|
||||||
|
if req.URL.Path == "/peer/_addroot" {
|
||||||
|
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||||
|
rsdata, err := ioutil.ReadAll(io.LimitReader(req.Body, 16384))
|
||||||
|
if err != nil || len(rsdata) == 0 {
|
||||||
|
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"read error"})
|
||||||
|
} else {
|
||||||
|
p, err := node.AddRoot(rsdata)
|
||||||
|
if err != nil {
|
||||||
|
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"invalid root spec"})
|
||||||
|
}
|
||||||
|
_ = apiSendObj(out, req, http.StatusOK, p)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Header().Set("Allow", "POST, PUT")
|
||||||
|
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"no root spec supplied"})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var queriedStr string
|
||||||
var queriedID Address
|
var queriedID Address
|
||||||
|
var queriedFP *Fingerprint
|
||||||
if len(req.URL.Path) > 6 {
|
if len(req.URL.Path) > 6 {
|
||||||
var err error
|
queriedStr = req.URL.Path[6:]
|
||||||
queriedID, err = NewAddressFromString(req.URL.Path[6:])
|
if len(queriedStr) == AddressStringLength {
|
||||||
|
queriedID, err = NewAddressFromString(queriedStr)
|
||||||
|
if err != nil {
|
||||||
|
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
queriedFP, err = NewFingerprintFromString(queriedStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Right now POST/PUT is only used with peers to add or remove root servers.
|
var peer *Peer
|
||||||
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
|
||||||
if queriedID == 0 {
|
|
||||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var peerChanges PeerMutableFields
|
|
||||||
if apiReadObj(out, req, &peerChanges) == nil {
|
|
||||||
if peerChanges.Root != nil || peerChanges.Bootstrap != nil {
|
|
||||||
peers := node.Peers()
|
peers := node.Peers()
|
||||||
|
if queriedFP != nil {
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
if p.Address == queriedID && (peerChanges.Identity == nil || peerChanges.Identity.Equals(p.Identity)) {
|
if p.Fingerprint.Equals(queriedFP) {
|
||||||
if peerChanges.Root != nil && *peerChanges.Root != p.Root {
|
peer = p
|
||||||
if *peerChanges.Root {
|
break
|
||||||
_ = node.AddRoot(p.Identity, peerChanges.Bootstrap)
|
|
||||||
} else {
|
|
||||||
node.RemoveRoot(p.Identity)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if queriedID != 0 {
|
||||||
|
for _, p := range peers {
|
||||||
|
if p.Address == queriedID {
|
||||||
|
peer = p
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Method == http.MethodGet || req.Method == http.MethodHead || req.Method == http.MethodPost || req.Method == http.MethodPut {
|
if req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||||
peers := node.Peers()
|
if peer != nil {
|
||||||
if queriedID != 0 {
|
var posted Peer
|
||||||
for _, p := range peers {
|
if apiReadObj(out, req, &posted) == nil {
|
||||||
if p.Address == queriedID {
|
if posted.Root && !peer.Root {
|
||||||
_ = apiSendObj(out, req, http.StatusOK, p)
|
_ = apiSendObj(out, req, http.StatusBadRequest, &APIErr{"root spec must be submitted to /peer/_addroot, post to peers can only be used to clear the root flag"})
|
||||||
return
|
} else if !posted.Root && peer.Root {
|
||||||
|
peer.Root = false
|
||||||
|
node.RemoveRoot(peer.Address)
|
||||||
|
_ = apiSendObj(out, req, http.StatusOK, peer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
||||||
|
}
|
||||||
|
} else if req.Method == http.MethodGet || req.Method == http.MethodHead || req.Method == http.MethodPost || req.Method == http.MethodPut {
|
||||||
|
if peer != nil {
|
||||||
|
_ = apiSendObj(out, req, http.StatusOK, peer)
|
||||||
|
} else if len(queriedStr) > 0 {
|
||||||
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
_ = apiSendObj(out, req, http.StatusNotFound, &APIErr{"peer not found"})
|
||||||
} else {
|
} else {
|
||||||
_ = apiSendObj(out, req, http.StatusOK, peers)
|
_ = apiSendObj(out, req, http.StatusOK, peers)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
out.Header().Set("Allow", "GET, HEAD, PUT, POST")
|
out.Header().Set("Allow", "GET, HEAD, POST, PUT")
|
||||||
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"peers are read only"})
|
_ = apiSendObj(out, req, http.StatusMethodNotAllowed, &APIErr{"unsupported method"})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
smux.HandleFunc("/network/", func(out http.ResponseWriter, req *http.Request) {
|
smux.HandleFunc("/network/", func(out http.ResponseWriter, req *http.Request) {
|
||||||
defer func() {
|
defer func() {
|
||||||
e := recover()
|
e := recover()
|
||||||
|
@ -496,8 +518,6 @@ func createAPIServer(basePath string, node *Node) (*http.Server, *http.Server, e
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
listener, err := createNamedSocketListener(basePath, APISocketName)
|
listener, err := createNamedSocketListener(basePath, APISocketName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
|
|
@ -18,6 +18,7 @@ package zerotier
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
@ -49,6 +50,10 @@ func (fp *Fingerprint) String() string {
|
||||||
return Base32StdLowerCase.EncodeToString(tmp[:])
|
return Base32StdLowerCase.EncodeToString(tmp[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fp *Fingerprint) Equals(fp2 *Fingerprint) bool {
|
||||||
|
return fp.Address == fp2.Address && bytes.Equal(fp.Hash[:], fp2.Hash[:])
|
||||||
|
}
|
||||||
|
|
||||||
func (fp *Fingerprint) apiFingerprint() *C.ZT_Fingerprint {
|
func (fp *Fingerprint) apiFingerprint() *C.ZT_Fingerprint {
|
||||||
var apifp C.ZT_Fingerprint
|
var apifp C.ZT_Fingerprint
|
||||||
apifp.address = C.uint64_t(fp.Address)
|
apifp.address = C.uint64_t(fp.Address)
|
||||||
|
|
|
@ -27,14 +27,15 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Constants from node/Identity.hpp (must be the same)
|
||||||
const (
|
const (
|
||||||
IdentityTypeC25519 = C.ZT_IDENTITY_TYPE_C25519
|
IdentityTypeC25519 = 0
|
||||||
IdentityTypeP384 = C.ZT_IDENTITY_TYPE_P384
|
IdentityTypeP384 = 1
|
||||||
|
|
||||||
IdentityTypeC25519PublicKeySize = C.ZT_IDENTITY_C25519_PUBLIC_KEY_SIZE
|
IdentityTypeC25519PublicKeySize = 64
|
||||||
IdentityTypeC25519PrivateKeySize = C.ZT_IDENTITY_C25519_PRIVATE_KEY_SIZE
|
IdentityTypeC25519PrivateKeySize = 64
|
||||||
IdentityTypeP384PublicKeySize = C.ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE
|
IdentityTypeP384PublicKeySize = 114
|
||||||
IdentityTypeP384PrivateKeySize = C.ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE
|
IdentityTypeP384PrivateKeySize = 112
|
||||||
)
|
)
|
||||||
|
|
||||||
// Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node
|
// Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node
|
||||||
|
@ -239,14 +240,14 @@ func (id *Identity) MakeRoot(addresses []InetAddress) ([]byte, error) {
|
||||||
return nil, errors.New("error initializing ZT_Identity")
|
return nil, errors.New("error initializing ZT_Identity")
|
||||||
}
|
}
|
||||||
|
|
||||||
ss := make([]C.sockaddr_storage, len(addresses))
|
ss := make([]C.struct_sockaddr_storage, len(addresses))
|
||||||
for i := range addresses {
|
for i := range addresses {
|
||||||
if !makeSockaddrStorage(addresses[i].IP, addresses[i].Port, &ss[i]) {
|
if !makeSockaddrStorage(addresses[i].IP, addresses[i].Port, &ss[i]) {
|
||||||
return nil, errors.New("invalid address in address list")
|
return nil, errors.New("invalid address in address list")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var buf [8192]byte
|
var buf [8192]byte
|
||||||
rl := C.ZT_Identity_makeRootSpecification(id.cid, C.int64_t(TimeMs()), &ss[0], C.uint(len(ss)), &buf[0], 8192)
|
rl := C.ZT_Identity_makeRootSpecification(id.cid, C.int64_t(TimeMs()), &ss[0], C.uint(len(ss)), unsafe.Pointer(&buf[0]), 8192)
|
||||||
if rl <= 0 {
|
if rl <= 0 {
|
||||||
return nil, errors.New("unable to make root specification (does identity contain a secret key?)")
|
return nil, errors.New("unable to make root specification (does identity contain a secret key?)")
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ const (
|
||||||
defaultVirtualNetworkMTU = C.ZT_DEFAULT_MTU
|
defaultVirtualNetworkMTU = C.ZT_DEFAULT_MTU
|
||||||
|
|
||||||
// maxCNodeRefs is the maximum number of Node instances that can be created in this process (increasing is fine)
|
// maxCNodeRefs is the maximum number of Node instances that can be created in this process (increasing is fine)
|
||||||
maxCNodeRefs = 4
|
maxCNodeRefs = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -90,6 +90,9 @@ func init() {
|
||||||
|
|
||||||
// Node is an instance of a virtual port on the global switch.
|
// Node is an instance of a virtual port on the global switch.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
// Time this node was created
|
||||||
|
startupTime int64
|
||||||
|
|
||||||
// an arbitrary uintptr given to the core as its pointer back to Go's Node instance
|
// an arbitrary uintptr given to the core as its pointer back to Go's Node instance
|
||||||
cPtr uintptr
|
cPtr uintptr
|
||||||
|
|
||||||
|
@ -146,13 +149,14 @@ type Node struct {
|
||||||
// NewNode creates and initializes a new instance of the ZeroTier node service
|
// NewNode creates and initializes a new instance of the ZeroTier node service
|
||||||
func NewNode(basePath string) (n *Node, err error) {
|
func NewNode(basePath string) (n *Node, err error) {
|
||||||
n = new(Node)
|
n = new(Node)
|
||||||
|
n.startupTime = TimeMs()
|
||||||
|
|
||||||
// Register this with the cNodeRefs lookup array and set up a deferred function
|
// Register this with the cNodeRefs lookup array and set up a deferred function
|
||||||
// to unregister this if we exit before the end of the constructor such as by
|
// to unregister this if we exit before the end of the constructor such as by
|
||||||
// returning an error.
|
// returning an error.
|
||||||
cPtr := -1
|
cPtr := -1
|
||||||
for i:=0;i<maxCNodeRefs;i++ {
|
for i := 0; i < maxCNodeRefs; i++ {
|
||||||
if atomic.CompareAndSwapUint32(&cNodeRefUsed[i],0,1) {
|
if atomic.CompareAndSwapUint32(&cNodeRefUsed[i], 0, 1) {
|
||||||
cNodeRefs[i] = n
|
cNodeRefs[i] = n
|
||||||
cPtr = i
|
cPtr = i
|
||||||
n.cPtr = uintptr(i)
|
n.cPtr = uintptr(i)
|
||||||
|
@ -164,7 +168,7 @@ func NewNode(basePath string) (n *Node, err error) {
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if cPtr >= 0 {
|
if cPtr >= 0 {
|
||||||
atomic.StoreUint32(&cNodeRefUsed[cPtr],0)
|
atomic.StoreUint32(&cNodeRefUsed[cPtr], 0)
|
||||||
cNodeRefs[cPtr] = nil
|
cNodeRefs[cPtr] = nil
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -331,7 +335,7 @@ func (n *Node) Close() {
|
||||||
n.runWaitGroup.Wait()
|
n.runWaitGroup.Wait()
|
||||||
|
|
||||||
cNodeRefs[n.cPtr] = nil
|
cNodeRefs[n.cPtr] = nil
|
||||||
atomic.StoreUint32(&cNodeRefUsed[n.cPtr],0)
|
atomic.StoreUint32(&cNodeRefUsed[n.cPtr], 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,11 +449,31 @@ func (n *Node) Leave(nwid NetworkID) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) AddRoot(spec []byte) error {
|
func (n *Node) AddRoot(spec []byte) (*Peer, error) {
|
||||||
return nil
|
if len(spec) == 0 {
|
||||||
|
return nil, ErrInvalidParameter
|
||||||
|
}
|
||||||
|
var address C.uint64_t
|
||||||
|
res := C.ZT_Node_addRoot(n.zn, nil, unsafe.Pointer(&spec[0]), C.uint(len(spec)), &address)
|
||||||
|
if res != 0 {
|
||||||
|
return nil, ErrInvalidParameter
|
||||||
|
}
|
||||||
|
peers := n.Peers()
|
||||||
|
for _, p := range peers {
|
||||||
|
if p.Address == Address(uint64(address)) {
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ErrInternal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) RemoveRoot(address Address) {
|
func (n *Node) RemoveRoot(address Address) {
|
||||||
|
var cfp C.ZT_Fingerprint
|
||||||
|
cfp.address = C.uint64_t(address)
|
||||||
|
for i := 0; i < 48; i++ {
|
||||||
|
cfp.hash[i] = 0
|
||||||
|
}
|
||||||
|
C.ZT_Node_removeRoot(n.zn, nil, &cfp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNetwork looks up a network by ID or returns nil if not joined
|
// GetNetwork looks up a network by ID or returns nil if not joined
|
||||||
|
@ -481,7 +505,8 @@ func (n *Node) Peers() []*Peer {
|
||||||
p2 := new(Peer)
|
p2 := new(Peer)
|
||||||
p2.Address = Address(p.address)
|
p2.Address = Address(p.address)
|
||||||
p2.Identity, _ = newIdentityFromCIdentity(unsafe.Pointer(p.identity))
|
p2.Identity, _ = newIdentityFromCIdentity(unsafe.Pointer(p.identity))
|
||||||
p2.Fingerprint = C.GoBytes(unsafe.Pointer(&p.fingerprint.hash[0]), 48)
|
p2.Fingerprint.Address = p2.Address
|
||||||
|
copy(p2.Fingerprint.Hash[:], ((*[48]byte)(unsafe.Pointer(&p.fingerprint.hash[0])))[:])
|
||||||
p2.Version = [3]int{int(p.versionMajor), int(p.versionMinor), int(p.versionRev)}
|
p2.Version = [3]int{int(p.versionMajor), int(p.versionMinor), int(p.versionRev)}
|
||||||
p2.Latency = int(p.latency)
|
p2.Latency = int(p.latency)
|
||||||
p2.Root = p.root != 0
|
p2.Root = p.root != 0
|
||||||
|
@ -498,7 +523,6 @@ func (n *Node) Peers() []*Peer {
|
||||||
Port: a.Port,
|
Port: a.Port,
|
||||||
LastSend: int64(pt.lastSend),
|
LastSend: int64(pt.lastSend),
|
||||||
LastReceive: int64(pt.lastReceive),
|
LastReceive: int64(pt.lastReceive),
|
||||||
TrustedPathID: uint64(pt.trustedPathId),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,7 +626,7 @@ func (n *Node) runMaintenance() {
|
||||||
}
|
}
|
||||||
for _, ip := range interfaceAddresses {
|
for _, ip := range interfaceAddresses {
|
||||||
for _, p := range ports {
|
for _, p := range ports {
|
||||||
a := InetAddress{ IP: ip, Port: p }
|
a := InetAddress{IP: ip, Port: p}
|
||||||
ak := a.key()
|
ak := a.key()
|
||||||
if _, have := externalAddresses[ak]; !have {
|
if _, have := externalAddresses[ak]; !have {
|
||||||
externalAddresses[ak] = &a
|
externalAddresses[ak] = &a
|
||||||
|
|
|
@ -21,5 +21,4 @@ type Path struct {
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
LastSend int64 `json:"lastSend"`
|
LastSend int64 `json:"lastSend"`
|
||||||
LastReceive int64 `json:"lastReceive"`
|
LastReceive int64 `json:"lastReceive"`
|
||||||
TrustedPathID uint64 `json:"trustedPathID"`
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,16 +17,10 @@ package zerotier
|
||||||
type Peer struct {
|
type Peer struct {
|
||||||
Address Address `json:"address"`
|
Address Address `json:"address"`
|
||||||
Identity *Identity `json:"identity"`
|
Identity *Identity `json:"identity"`
|
||||||
Fingerprint []byte `json:"fingerprint"`
|
Fingerprint Fingerprint `json:"fingerprint"`
|
||||||
Version [3]int `json:"version"`
|
Version [3]int `json:"version"`
|
||||||
Latency int `json:"latency"`
|
Latency int `json:"latency"`
|
||||||
Root bool `json:"root"`
|
Root bool `json:"root"`
|
||||||
Bootstrap *InetAddress `json:"bootstrap,omitempty"`
|
Bootstrap *InetAddress `json:"bootstrap,omitempty"`
|
||||||
Paths []Path `json:"paths,omitempty"`
|
Paths []Path `json:"paths,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PeerMutableFields contains only the mutable fields of Peer as nullable pointers.
|
|
||||||
type PeerMutableFields struct {
|
|
||||||
Root *bool `json:"root"`
|
|
||||||
RootSpec []byte `json:"rootSpec"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -1755,9 +1755,10 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_
|
||||||
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
* @param tptr Thread pointer to pass to functions/callbacks resulting from this call
|
||||||
* @param rdef Root definition (serialized identity and locator)
|
* @param rdef Root definition (serialized identity and locator)
|
||||||
* @param rdeflen Length of root definition in bytes
|
* @param rdeflen Length of root definition in bytes
|
||||||
|
* @param address If non-NULL will be filled with the ZeroTier address of the root (only defined if return is OK)
|
||||||
* @return OK (0) or error code if a fatal error condition has occurred
|
* @return OK (0) or error code if a fatal error condition has occurred
|
||||||
*/
|
*/
|
||||||
ZT_SDK_API enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,void *tptr,const void *rdef,unsigned int rdeflen);
|
ZT_SDK_API enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,void *tptr,const void *rdef,unsigned int rdeflen,uint64_t *address);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a root
|
* Remove a root
|
||||||
|
|
|
@ -224,9 +224,6 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr,int64_t now,volatile int64
|
||||||
|
|
||||||
if (pf.online) {
|
if (pf.online) {
|
||||||
// If we have at least one online root, request whois for roots not online.
|
// If we have at least one online root, request whois for roots not online.
|
||||||
// This will give us updated locators for these roots which may contain new
|
|
||||||
// IP addresses. It will also auto-discover IPs for roots that were not added
|
|
||||||
// with an initial bootstrap address.
|
|
||||||
// TODO
|
// TODO
|
||||||
//for (Vector<Address>::const_iterator r(pf.rootsNotOnline.begin()); r != pf.rootsNotOnline.end(); ++r)
|
//for (Vector<Address>::const_iterator r(pf.rootsNotOnline.begin()); r != pf.rootsNotOnline.end(); ++r)
|
||||||
// RR->sw->requestWhois(tPtr,now,*r);
|
// RR->sw->requestWhois(tPtr,now,*r);
|
||||||
|
@ -339,11 +336,13 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
|
||||||
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZT_ResultCode Node::addRoot(void *tPtr,const void *rdef,unsigned int rdeflen)
|
ZT_ResultCode Node::addRoot(void *tPtr,const void *rdef,unsigned int rdeflen,uint64_t *address)
|
||||||
{
|
{
|
||||||
if ((!rdef)||(rdeflen == 0))
|
if ((!rdef)||(rdeflen == 0))
|
||||||
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
return ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||||
std::pair<Identity,Locator> r(Locator::parseRootSpecification(rdef,rdeflen));
|
std::pair<Identity,Locator> r(Locator::parseRootSpecification(rdef,rdeflen));
|
||||||
|
if (address)
|
||||||
|
*address = r.first.address().toInt();
|
||||||
return ((r.first)&&(RR->topology->addRoot(tPtr,r.first,r.second))) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
|
return ((r.first)&&(RR->topology->addRoot(tPtr,r.first,r.second))) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -862,10 +861,10 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node,uint64_t nwid,uint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,void *tptr,const void *rdef,unsigned int rdeflen)
|
enum ZT_ResultCode ZT_Node_addRoot(ZT_Node *node,void *tptr,const void *rdef,unsigned int rdeflen,uint64_t *address)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return reinterpret_cast<ZeroTier::Node *>(node)->addRoot(tptr,rdef,rdeflen);
|
return reinterpret_cast<ZeroTier::Node *>(node)->addRoot(tptr,rdef,rdeflen,address);
|
||||||
} catch (std::bad_alloc &exc) {
|
} catch (std::bad_alloc &exc) {
|
||||||
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY;
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
|
|
|
@ -92,7 +92,7 @@ public:
|
||||||
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
|
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
|
||||||
ZT_ResultCode multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
ZT_ResultCode multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||||
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
|
||||||
ZT_ResultCode addRoot(void *tptr,const void *rdef,unsigned int rdeflen);
|
ZT_ResultCode addRoot(void *tptr,const void *rdef,unsigned int rdeflen,uint64_t *address);
|
||||||
ZT_ResultCode removeRoot(void *tptr,const ZT_Fingerprint *fp);
|
ZT_ResultCode removeRoot(void *tptr,const ZT_Fingerprint *fp);
|
||||||
uint64_t address() const;
|
uint64_t address() const;
|
||||||
void status(ZT_NodeStatus *status) const;
|
void status(ZT_NodeStatus *status) const;
|
||||||
|
|
Loading…
Add table
Reference in a new issue