mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-02-01 16:58:09 +00:00
A bunch of CLI work
This commit is contained in:
parent
c4504fd3ff
commit
7fc78129f4
@ -14,6 +14,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -43,3 +44,8 @@ func enabledDisabled(f bool) string {
|
||||
}
|
||||
return "DISABLED"
|
||||
}
|
||||
|
||||
func jsonDump(obj interface{}) string {
|
||||
j, _ := json.MarshalIndent(obj, "", " ")
|
||||
return string(j)
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
@ -26,7 +27,7 @@ Licensed under the ZeroTier BSL (see LICENSE.txt)`, zerotier.CoreVersionMajor, z
|
||||
func Help() {
|
||||
fmt.Println(copyrightText)
|
||||
fmt.Println(`
|
||||
Usage: zerotier [-options] <command> [-options] [command args]
|
||||
Usage: zerotier [-options] <command> [command args]
|
||||
|
||||
Global Options:
|
||||
-j Output raw JSON where applicable
|
||||
@ -40,11 +41,18 @@ Commands:
|
||||
status Show ZeroTier service status and config
|
||||
peers Show VL1 peers
|
||||
roots Show VL1 root servers
|
||||
addroot <locator> [<name>] Add a VL1 root
|
||||
addroot <locator> [name] Add a VL1 root
|
||||
removeroot <name> Remove a VL1 root
|
||||
makelocator <secret> <address> [...] Make and sign a locator
|
||||
makelocatordnskey Create a new secure DNS name and key
|
||||
makelocatordns <key> <locator> Make DNS TXT records for a locator
|
||||
locator <command> [args] Locator management commands
|
||||
new <identity> <address> [...] Create and sign a locator
|
||||
newdnskey Create a secure DNS name and secret
|
||||
getdns <key> <locator> Create secure DNS TXT records
|
||||
identity <command> [args] Identity management commands
|
||||
new Create new identity (including secret)
|
||||
getpublic <identity> Extract only public part of identity
|
||||
validate <identity> Locally validate an identity
|
||||
sign <identity> <file> Sign a file with an identity's key
|
||||
verify <identity> <file> <sig> Verify a signature
|
||||
networks Show joined VL2 virtual networks
|
||||
join <network ID> Join a virtual network
|
||||
leave <network ID> Leave a virtual network
|
||||
|
@ -13,6 +13,6 @@
|
||||
|
||||
package cli
|
||||
|
||||
// MakeLocator CLI command
|
||||
func MakeLocator(args []string) {
|
||||
// Identity command
|
||||
func Identity(args []string) {
|
||||
}
|
135
go/cmd/zerotier/cli/locator.go
Normal file
135
go/cmd/zerotier/cli/locator.go
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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 cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
func locatorNew(args []string) {
|
||||
if len(args) < 2 {
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
identityData, err := ioutil.ReadFile(args[0])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: unable to read identity: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
identity, err := zerotier.NewIdentityFromString(string(identityData))
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: invalid identity: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
if !identity.HasPrivate() {
|
||||
fmt.Println("FATAL: identity does not contain secret key")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var virt []*zerotier.Identity
|
||||
var phys []*zerotier.InetAddress
|
||||
for i := 1; i < len(args); i++ {
|
||||
if strings.Contains(args[i], "/") {
|
||||
a := zerotier.NewInetAddressFromString(args[i])
|
||||
if a == nil {
|
||||
fmt.Printf("FATAL: IP/port address '%s' is not valid\n", args[i])
|
||||
os.Exit(1)
|
||||
}
|
||||
phys = append(phys, a)
|
||||
} else {
|
||||
a, err := zerotier.NewIdentityFromString(args[i])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: identity (virtual address) '%s' is not valid: %s\n", args[i], err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
virt = append(virt, a)
|
||||
}
|
||||
}
|
||||
|
||||
loc, err := zerotier.NewLocator(identity, virt, phys)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: internal error creating locator: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(jsonDump(loc))
|
||||
}
|
||||
|
||||
func locatorNewDNSKey(args []string) {
|
||||
if len(args) != 0 {
|
||||
Help()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
sk, err := zerotier.NewLocatorDNSSigningKey()
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: error creating secure DNS signing key: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(jsonDump(sk))
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func locatorGetDNS(args []string) {
|
||||
if len(args) < 2 {
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
keyData, err := ioutil.ReadFile(args[0])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: unable to read secure DNS key file: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
var sk zerotier.LocatorDNSSigningKey
|
||||
err = json.Unmarshal(keyData, &sk)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: DNS key file invalid: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
locData, err := ioutil.ReadFile(args[1])
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: unable to read locator: %s\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
var loc zerotier.Locator
|
||||
err = json.Unmarshal(locData, &loc)
|
||||
if err != nil {
|
||||
fmt.Printf("FATAL: locator invalid: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Locator CLI command
|
||||
func Locator(args []string) {
|
||||
if len(args) > 0 {
|
||||
switch args[0] {
|
||||
case "new":
|
||||
locatorNew(args[1:])
|
||||
case "newdnskey":
|
||||
locatorNewDNSKey(args[1:])
|
||||
case "getdns":
|
||||
locatorGetDNS(args[1:])
|
||||
}
|
||||
}
|
||||
Help()
|
||||
os.Exit(1)
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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 cli
|
||||
|
||||
// MakeLocatorDNS CLI command
|
||||
func MakeLocatorDNS(args []string) {
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (c)2019 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: 2023-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 cli
|
||||
|
||||
// MakeLocatorDNSKey CLI command
|
||||
func MakeLocatorDNSKey(args []string) {
|
||||
}
|
@ -14,9 +14,9 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
@ -26,8 +26,7 @@ func Peers(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
apiGet(basePath, authToken, "/peer", &peers)
|
||||
|
||||
if jsonOutput {
|
||||
j, _ := json.MarshalIndent(&peers, "", " ")
|
||||
fmt.Println(string(j))
|
||||
fmt.Println(jsonDump(&peers))
|
||||
} else {
|
||||
fmt.Printf("<ztaddr> <ver> <role> <lat> <link> <lastTX> <lastRX> <path(s)>\n")
|
||||
for _, peer := range peers {
|
||||
|
@ -14,9 +14,9 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
|
||||
@ -26,8 +26,7 @@ func Status(basePath, authToken string, args []string, jsonOutput bool) {
|
||||
apiGet(basePath, authToken, "/status", &status)
|
||||
|
||||
if jsonOutput {
|
||||
j, _ := json.MarshalIndent(&status, "", " ")
|
||||
fmt.Println(string(j))
|
||||
fmt.Println(jsonDump(&status))
|
||||
} else {
|
||||
online := "ONLINE"
|
||||
if !status.Online {
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"zerotier/cmd/zerotier/cli"
|
||||
"zerotier/pkg/zerotier"
|
||||
)
|
||||
@ -112,7 +113,7 @@ func main() {
|
||||
case "peers", "listpeers":
|
||||
authTokenRequired(authToken)
|
||||
cli.Peers(basePath, authToken, cmdArgs, *jflag)
|
||||
case "roots":
|
||||
case "roots", "listroots", "listmoons":
|
||||
authTokenRequired(authToken)
|
||||
cli.Roots(basePath, authToken, cmdArgs)
|
||||
case "addroot":
|
||||
@ -121,12 +122,10 @@ func main() {
|
||||
case "removeroot":
|
||||
authTokenRequired(authToken)
|
||||
cli.RemoveRoot(basePath, authToken, cmdArgs)
|
||||
case "makelocator":
|
||||
cli.MakeLocator(cmdArgs)
|
||||
case "makelocatordnskey":
|
||||
cli.MakeLocatorDNSKey(cmdArgs)
|
||||
case "makelocatordns":
|
||||
cli.MakeLocatorDNS(cmdArgs)
|
||||
case "locator":
|
||||
cli.Locator(cmdArgs)
|
||||
case "identity":
|
||||
cli.Identity(cmdArgs)
|
||||
case "networks", "listnetworks":
|
||||
authTokenRequired(authToken)
|
||||
cli.Networks(basePath, authToken, cmdArgs)
|
||||
|
@ -732,7 +732,7 @@ extern "C" int ZT_GoLocator_makeSecureDNSName(char *name,unsigned int nameBufSiz
|
||||
const Str n(Locator::makeSecureDnsName(pub));
|
||||
if (n.length() >= nameBufSize)
|
||||
return -1;
|
||||
Utils::scopy(name,sizeof(name),n.c_str());
|
||||
Utils::scopy(name,nameBufSize,n.c_str());
|
||||
return ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,6 @@ int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorS
|
||||
int ZT_GoLocator_makeSignedTxtRecords(
|
||||
const uint8_t *locator,
|
||||
unsigned int locatorSize,
|
||||
int64_t ts,
|
||||
const char *name,
|
||||
const uint8_t *privateKey,
|
||||
unsigned int privateKeySize,
|
||||
|
@ -45,7 +45,7 @@ type Identity struct {
|
||||
// NewIdentityFromString generates a new identity from its string representation.
|
||||
// The private key is imported as well if it is present.
|
||||
func NewIdentityFromString(s string) (*Identity, error) {
|
||||
ss := strings.Split(s, ":")
|
||||
ss := strings.Split(strings.TrimSpace(s), ":")
|
||||
if len(ss) < 3 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ func (i *InetAddress) Less(i2 *InetAddress) bool {
|
||||
// NewInetAddressFromString parses an IP[/port] format address
|
||||
func NewInetAddressFromString(s string) *InetAddress {
|
||||
i := new(InetAddress)
|
||||
ss := strings.Split(s, "/")
|
||||
ss := strings.Split(strings.TrimSpace(s), "/")
|
||||
if len(ss) > 0 {
|
||||
i.IP = net.ParseIP(ss[0])
|
||||
i4 := i.IP.To4()
|
||||
|
@ -151,6 +151,25 @@ func NewLocatorFromBytes(b []byte) (*Locator, error) {
|
||||
return &loc, nil
|
||||
}
|
||||
|
||||
// MakeTXTRecords creates secure DNS TXT records for this locator
|
||||
func (l *Locator) MakeTXTRecords(key *LocatorDNSSigningKey) ([]string, error) {
|
||||
if key == nil || len(l.Bytes) == 0 || len(key.PrivateKey) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
var results [256][256]C.char
|
||||
cName := C.CString(key.SecureDNSName)
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
count := int(C.ZT_GoLocator_makeSignedTxtRecords((*C.uint8_t)(&l.Bytes[0]), C.uint(len(l.Bytes)), cName, (*C.uint8_t)(&key.PrivateKey[0]), C.uint(len(key.PrivateKey)), &results[0]))
|
||||
if count > 0 {
|
||||
var t []string
|
||||
for i := 0; i < int(count); i++ {
|
||||
t = append(t, C.GoString(&results[i][0]))
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
return nil, ErrInternal
|
||||
}
|
||||
|
||||
// MarshalJSON marshals this Locator as its byte encoding
|
||||
func (l *Locator) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(l)
|
||||
|
@ -71,6 +71,9 @@ const (
|
||||
// AFInet6 is the address family for IPv6
|
||||
AFInet6 = C.AF_INET6
|
||||
|
||||
networkConfigOpUp int = C.ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP
|
||||
networkConfigOpUpdate int = C.ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE
|
||||
|
||||
defaultVirtualNetworkMTU = C.ZT_DEFAULT_MTU
|
||||
)
|
||||
|
||||
@ -548,21 +551,11 @@ func (n *Node) Roots() []*Root {
|
||||
if rl != nil {
|
||||
for i := 0; i < int(rl.count); i++ {
|
||||
root := (*C.ZT_Root)(unsafe.Pointer(uintptr(unsafe.Pointer(rl)) + C.sizeof_ZT_RootList))
|
||||
id, err := NewIdentityFromString(C.GoString(root.identity))
|
||||
if err == nil {
|
||||
var addrs []InetAddress
|
||||
for j := uintptr(0); j < uintptr(root.addressCount); j++ {
|
||||
a := NewInetAddressFromSockaddr(unsafe.Pointer(uintptr(unsafe.Pointer(root.addresses)) + (j * C.sizeof_struct_sockaddr_storage)))
|
||||
if a != nil && a.Valid() {
|
||||
addrs = append(addrs, *a)
|
||||
}
|
||||
}
|
||||
loc, _ := NewLocatorFromBytes(C.GoBytes(root.locator, C.int(root.locatorSize)))
|
||||
if loc != nil {
|
||||
roots = append(roots, &Root{
|
||||
Name: C.GoString(root.name),
|
||||
Identity: id,
|
||||
Addresses: addrs,
|
||||
Preferred: root.preferred != 0,
|
||||
Online: root.online != 0,
|
||||
Name: C.GoString(root.name),
|
||||
Locator: loc,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -584,11 +577,11 @@ func (n *Node) SetRoot(name string, locator *Locator) error {
|
||||
}
|
||||
var lb []byte
|
||||
if locator != nil {
|
||||
lb = locator.Bytes()
|
||||
lb = locator.Bytes
|
||||
}
|
||||
var lbp unsafe.Pointer
|
||||
if len(lb) > 0 {
|
||||
lbp = &lb[0]
|
||||
lbp = unsafe.Pointer(&lb[0])
|
||||
}
|
||||
cn := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cn))
|
||||
@ -925,8 +918,8 @@ func goVirtualNetworkConfigFunc(gn, _ unsafe.Pointer, nwid C.uint64_t, op C.int,
|
||||
node.networksLock.RUnlock()
|
||||
|
||||
if network != nil {
|
||||
switch op {
|
||||
case C.ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, C.ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP:
|
||||
switch int(op) {
|
||||
case networkConfigOpUp, networkConfigOpUpdate:
|
||||
ncc := (*C.ZT_VirtualNetworkConfig)(conf)
|
||||
if network.networkConfigRevision() > uint64(ncc.netconfRevision) {
|
||||
return
|
||||
|
@ -15,8 +15,6 @@ package zerotier
|
||||
|
||||
// Root describes a root server used to find and establish communication with other nodes.
|
||||
type Root struct {
|
||||
Name string
|
||||
Locator *Locator
|
||||
Preferred bool
|
||||
Online bool
|
||||
Name string
|
||||
Locator *Locator
|
||||
}
|
||||
|
@ -532,29 +532,14 @@ typedef struct {
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Current public identity or NULL if not known (only possible with dynamic roots)
|
||||
* Serialized locator
|
||||
*/
|
||||
const char *identity;
|
||||
const void *locator;
|
||||
|
||||
/**
|
||||
* Current physical address(es) of this root
|
||||
* The size of locator in bytes
|
||||
*/
|
||||
const struct sockaddr_storage *addresses;
|
||||
|
||||
/**
|
||||
* Number of physical addresses
|
||||
*/
|
||||
unsigned int addressCount;
|
||||
|
||||
/**
|
||||
* If true, this is the current preferred root
|
||||
*/
|
||||
int preferred;
|
||||
|
||||
/**
|
||||
* If true, this root server appears online
|
||||
*/
|
||||
int online;
|
||||
unsigned int locatorSize;
|
||||
} ZT_Root;
|
||||
|
||||
/**
|
||||
|
@ -104,8 +104,7 @@ public:
|
||||
_l = ZT_STR_CAPACITY;
|
||||
throw ZT_EXCEPTION_OUT_OF_BOUNDS;
|
||||
}
|
||||
_s[l++] = *s;
|
||||
++s;
|
||||
_s[l++] = *(s++);
|
||||
}
|
||||
_s[l] = 0;
|
||||
_l = (uint8_t)l;
|
||||
|
@ -360,63 +360,32 @@ public:
|
||||
*/
|
||||
inline ZT_RootList *apiRoots(const int64_t now) const
|
||||
{
|
||||
ScopedPtr< Buffer<65536> > lbuf(new Buffer<65536>());
|
||||
Mutex::Lock l2(_roots_l);
|
||||
|
||||
// The memory allocated here has room for all roots plus the maximum size
|
||||
// of their DNS names, identities, and up to 16 physical addresses. Most
|
||||
// roots will have two: one V4 and one V6.
|
||||
const unsigned int totalRoots = _roots.size();
|
||||
ZT_RootList *rl = reinterpret_cast<ZT_RootList *>(malloc(sizeof(ZT_RootList) + (sizeof(ZT_Root) * totalRoots) + ((sizeof(struct sockaddr_storage) * ZT_MAX_PEER_NETWORK_PATHS) * totalRoots) + ((ZT_IDENTITY_STRING_BUFFER_LENGTH + 1024) * totalRoots)));
|
||||
if (!rl) {
|
||||
ZT_RootList *rl = (ZT_RootList *)malloc(sizeof(ZT_RootList) + (sizeof(ZT_Root) * _roots.size()) + (256 * _roots.size()) + (65536 * _roots.size()));
|
||||
if (!rl)
|
||||
return nullptr;
|
||||
}
|
||||
char *nptr = ((char *)rl) + sizeof(ZT_RootList) + (sizeof(ZT_Root) * _roots.size());
|
||||
uint8_t *lptr = ((uint8_t *)nptr) + (256 * _roots.size());
|
||||
|
||||
unsigned int c = 0;
|
||||
char *nameBufPtr = reinterpret_cast<char *>(rl) + sizeof(ZT_RootList) + (sizeof(ZT_Root) * totalRoots);
|
||||
struct sockaddr_storage *addrBuf = reinterpret_cast<struct sockaddr_storage *>(nameBufPtr);
|
||||
nameBufPtr += (sizeof(struct sockaddr_storage) * ZT_MAX_PEER_NETWORK_PATHS) * totalRoots;
|
||||
|
||||
_bestRoot_l.lock();
|
||||
const Peer *const bestRootPtr = _bestRoot.ptr();
|
||||
_bestRoot_l.unlock();
|
||||
|
||||
{
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_roots);
|
||||
while (i.next(k,v)) {
|
||||
rl->roots[c].name = nameBufPtr;
|
||||
const char *p = k->c_str();
|
||||
while (*p)
|
||||
*(nameBufPtr++) = *(p++);
|
||||
*(nameBufPtr++) = (char)0;
|
||||
|
||||
if (v->id()) {
|
||||
rl->roots[c].identity = nameBufPtr;
|
||||
v->id().toString(false,nameBufPtr);
|
||||
nameBufPtr += strlen(nameBufPtr) + 1;
|
||||
}
|
||||
|
||||
rl->roots[c].addresses = addrBuf;
|
||||
unsigned int ac = 0;
|
||||
for(unsigned int j=(unsigned int)v->phy().size();(ac<j)&&(ac<16);++ac)
|
||||
*(addrBuf++) = v->phy()[ac];
|
||||
rl->roots[c].addressCount = ac;
|
||||
|
||||
_peers_l.lock();
|
||||
const SharedPtr<Peer> *psptr = _peers.get(v->id().address());
|
||||
if (psptr) {
|
||||
rl->roots[c].preferred = (psptr->ptr() == bestRootPtr) ? 1 : 0;
|
||||
rl->roots[c].online = (*psptr)->alive(now) ? 1 : 0;
|
||||
}
|
||||
_peers_l.unlock();
|
||||
|
||||
++c;
|
||||
}
|
||||
Str *k = (Str *)0;
|
||||
Locator *v = (Locator *)0;
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_roots);
|
||||
while (i.next(k,v)) {
|
||||
Utils::scopy(nptr,256,k->c_str());
|
||||
rl->roots[c].name = nptr;
|
||||
nptr += 256;
|
||||
lbuf->clear();
|
||||
v->serialize(*lbuf);
|
||||
memcpy(lptr,lbuf->unsafeData(),lbuf->size());
|
||||
rl->roots[c].locator = lptr;
|
||||
rl->roots[c].locatorSize = lbuf->size();
|
||||
lptr += 65536;
|
||||
++c;
|
||||
}
|
||||
|
||||
rl->count = c;
|
||||
|
||||
return rl;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user