mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 21:13:44 +02:00
Go F yourself
This commit is contained in:
parent
6ce4663a31
commit
24904c5083
7 changed files with 405 additions and 22 deletions
|
@ -2,4 +2,7 @@ module zerotier
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
require (
|
||||||
|
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7
|
||||||
|
)
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ=
|
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 h1:S4qyfL2sEm5Budr4KVMyEniCy+PbS55651I/a+Kn/NQ=
|
||||||
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E=
|
github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95/go.mod h1:QiyDdbZLaJ/mZP4Zwc9g2QsfaEA4o7XvvgZegSci5/E=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
|
||||||
|
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
|
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259 h1:so6Hr/LodwSZ5UQDu/7PmQiDeS112WwtLvU3lpSPZTU=
|
||||||
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190529164535-6a60838ec259/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|
109
go/pkg/zerotier/base62.go
Normal file
109
go/pkg/zerotier/base62.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
* 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 zerotier
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Base62Alphabet is the alphabet used for LF's Base62 encoding.
|
||||||
|
const Base62Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
var base62Encoding, _ = newBaseXEncoding(Base62Alphabet)
|
||||||
|
|
||||||
|
type baseXEncoding struct {
|
||||||
|
base int
|
||||||
|
alphabet []rune
|
||||||
|
alphabetMap map[rune]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBaseXEncoding(alphabet string) (*baseXEncoding, error) {
|
||||||
|
runes := []rune(alphabet)
|
||||||
|
runeMap := make(map[rune]int)
|
||||||
|
for i := 0; i < len(runes); i++ {
|
||||||
|
if _, ok := runeMap[runes[i]]; ok {
|
||||||
|
return nil, errors.New("bad alphabet")
|
||||||
|
}
|
||||||
|
runeMap[runes[i]] = i
|
||||||
|
}
|
||||||
|
return &baseXEncoding{
|
||||||
|
base: len(runes),
|
||||||
|
alphabet: runes,
|
||||||
|
alphabetMap: runeMap,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *baseXEncoding) encode(source []byte) string {
|
||||||
|
if len(source) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
digits := []int{0}
|
||||||
|
for i := 0; i < len(source); i++ {
|
||||||
|
carry := int(source[i])
|
||||||
|
for j := 0; j < len(digits); j++ {
|
||||||
|
carry += digits[j] << 8
|
||||||
|
digits[j] = carry % e.base
|
||||||
|
carry = carry / e.base
|
||||||
|
}
|
||||||
|
for carry > 0 {
|
||||||
|
digits = append(digits, carry%e.base)
|
||||||
|
carry = carry / e.base
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var res bytes.Buffer
|
||||||
|
for k := 0; source[k] == 0 && k < len(source)-1; k++ {
|
||||||
|
res.WriteRune(e.alphabet[0])
|
||||||
|
}
|
||||||
|
for q := len(digits) - 1; q >= 0; q-- {
|
||||||
|
res.WriteRune(e.alphabet[digits[q]])
|
||||||
|
}
|
||||||
|
return res.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *baseXEncoding) decode(source string) []byte {
|
||||||
|
if len(source) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
runes := []rune(source)
|
||||||
|
bytes := []byte{0}
|
||||||
|
for i := 0; i < len(source); i++ {
|
||||||
|
value, ok := e.alphabetMap[runes[i]]
|
||||||
|
if ok { // ignore non-base characters
|
||||||
|
carry := int(value)
|
||||||
|
for j := 0; j < len(bytes); j++ {
|
||||||
|
carry += int(bytes[j]) * e.base
|
||||||
|
bytes[j] = byte(carry & 0xff)
|
||||||
|
carry >>= 8
|
||||||
|
}
|
||||||
|
for carry > 0 {
|
||||||
|
bytes = append(bytes, byte(carry&0xff))
|
||||||
|
carry >>= 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k := 0; runes[k] == e.alphabet[0] && k < len(runes)-1; k++ {
|
||||||
|
bytes = append(bytes, 0)
|
||||||
|
}
|
||||||
|
for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 {
|
||||||
|
bytes[i], bytes[j] = bytes[j], bytes[i]
|
||||||
|
}
|
||||||
|
return bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base62Encode encodes a byte array in base62 form
|
||||||
|
func Base62Encode(in []byte) string { return base62Encoding.encode(in) }
|
||||||
|
|
||||||
|
// Base62Decode decodes a base62 string into a byte array, ignoring non-base62 characters
|
||||||
|
func Base62Decode(in string) []byte { return base62Encoding.decode(in) }
|
56
go/pkg/zerotier/blob.go
Normal file
56
go/pkg/zerotier/blob.go
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* 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 zerotier
|
||||||
|
|
||||||
|
// This is copied from the LF code base to make JSON blob encoding uniform
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"unicode/utf8"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Blob is a byte array that serializes to a string or a base62 string prefixed by \b (binary)
|
||||||
|
type Blob []byte
|
||||||
|
|
||||||
|
// MarshalJSON returns this blob marshaled as a string using \b<base62> for non-UTF8 binary data.
|
||||||
|
func (b Blob) MarshalJSON() ([]byte, error) {
|
||||||
|
if utf8.Valid(b) {
|
||||||
|
return json.Marshal(string(b))
|
||||||
|
}
|
||||||
|
return []byte("\"\\b" + Base62Encode(b) + "\""), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON unmarshals this blob from a string or byte array.
|
||||||
|
func (b *Blob) UnmarshalJSON(j []byte) error {
|
||||||
|
var s string
|
||||||
|
err := json.Unmarshal(j, &s)
|
||||||
|
if err == nil {
|
||||||
|
if len(s) == 0 {
|
||||||
|
*b = nil
|
||||||
|
} else if s[0] == '\b' {
|
||||||
|
*b = Base62Decode(s[1:])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
*b = []byte(s)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Byte arrays are also accepted
|
||||||
|
var bb []byte
|
||||||
|
if json.Unmarshal(j, &bb) != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*b = bb
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -20,7 +20,10 @@ func (e Err) Error() string { return (string)(e) }
|
||||||
|
|
||||||
// Simple ZeroTier Errors
|
// Simple ZeroTier Errors
|
||||||
const (
|
const (
|
||||||
|
ErrNodeInitFailed Err = "unable to initialize core Node instance"
|
||||||
ErrInvalidMACAddress Err = "invalid MAC address"
|
ErrInvalidMACAddress Err = "invalid MAC address"
|
||||||
ErrInvalidZeroTierAddress Err = "invalid ZeroTier address"
|
ErrInvalidZeroTierAddress Err = "invalid ZeroTier address"
|
||||||
ErrInvalidParameter Err = "invalid parameter"
|
ErrInvalidParameter Err = "invalid parameter"
|
||||||
|
ErrTapInitFailed Err = "unable to create native Tap instance"
|
||||||
|
ErrUncrecognizedIdentityType Err = "unrecognized identity type"
|
||||||
)
|
)
|
||||||
|
|
192
go/pkg/zerotier/identity.go
Normal file
192
go/pkg/zerotier/identity.go
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
/*
|
||||||
|
* 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 zerotier
|
||||||
|
|
||||||
|
import (
|
||||||
|
secrand "crypto/rand"
|
||||||
|
"crypto/sha512"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/salsa20/salsa"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ztIdentityGenMemory = 2097152
|
||||||
|
const ztIdentityHashCashFirstByteLessThan = 17
|
||||||
|
|
||||||
|
// IdentityTypeC25519 is a classic Curve25519/Ed25519 identity
|
||||||
|
const IdentityTypeC25519 = 0
|
||||||
|
|
||||||
|
// IdentityTypeP384 is an identity containing both NIST P-384 and Curve25519/Ed25519 key types and leveraging both when possible
|
||||||
|
const IdentityTypeP384 = 1
|
||||||
|
|
||||||
|
func computeZeroTierIdentityMemoryHardHash(publicKey []byte) []byte {
|
||||||
|
s512 := sha512.Sum512(publicKey)
|
||||||
|
|
||||||
|
var genmem [ztIdentityGenMemory]byte
|
||||||
|
var s20key [32]byte
|
||||||
|
var s20ctr [16]byte
|
||||||
|
var s20ctri uint64
|
||||||
|
copy(s20key[:], s512[0:32])
|
||||||
|
copy(s20ctr[0:8], s512[32:40])
|
||||||
|
salsa.XORKeyStream(genmem[0:64], genmem[0:64], &s20ctr, &s20key)
|
||||||
|
s20ctri++
|
||||||
|
for i := 64; i < ztIdentityGenMemory; i += 64 {
|
||||||
|
binary.LittleEndian.PutUint64(s20ctr[8:16], s20ctri)
|
||||||
|
salsa.XORKeyStream(genmem[i:i+64], genmem[i-64:i], &s20ctr, &s20key)
|
||||||
|
s20ctri++
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp [8]byte
|
||||||
|
for i := 0; i < ztIdentityGenMemory; {
|
||||||
|
idx1 := uint(binary.BigEndian.Uint64(genmem[i:])&7) * 8
|
||||||
|
i += 8
|
||||||
|
idx2 := (uint(binary.BigEndian.Uint64(genmem[i:])) % uint(ztIdentityGenMemory/8)) * 8
|
||||||
|
i += 8
|
||||||
|
gm := genmem[idx2 : idx2+8]
|
||||||
|
d := s512[idx1 : idx1+8]
|
||||||
|
copy(tmp[:], gm)
|
||||||
|
copy(gm, d)
|
||||||
|
copy(d, tmp[:])
|
||||||
|
binary.LittleEndian.PutUint64(s20ctr[8:16], s20ctri)
|
||||||
|
salsa.XORKeyStream(s512[:], s512[:], &s20ctr, &s20key)
|
||||||
|
s20ctri++
|
||||||
|
}
|
||||||
|
|
||||||
|
return s512[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateDualPair generates a key pair containing two pairs: one for curve25519 and one for ed25519.
|
||||||
|
func generateDualPair() (pub [64]byte, priv [64]byte) {
|
||||||
|
k0pub, k0priv, _ := ed25519.GenerateKey(secrand.Reader)
|
||||||
|
var k1pub, k1priv [32]byte
|
||||||
|
secrand.Read(k1priv[:])
|
||||||
|
curve25519.ScalarBaseMult(&k1pub, &k1priv)
|
||||||
|
copy(pub[0:32], k1pub[:])
|
||||||
|
copy(pub[32:64], k0pub[0:32])
|
||||||
|
copy(priv[0:32], k1priv[:])
|
||||||
|
copy(priv[32:64], k0priv[0:32])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identity is precisely what it sounds like: the address and associated keys for a ZeroTier node
|
||||||
|
type Identity struct {
|
||||||
|
// Address is this identity's 40-bit short address
|
||||||
|
Address Address
|
||||||
|
|
||||||
|
// Type is either IdentityTypeC25519 or IdentityTypeP384
|
||||||
|
Type int
|
||||||
|
|
||||||
|
// PublicKey is this identity's public key bytes
|
||||||
|
PublicKey Blob
|
||||||
|
|
||||||
|
privateKey []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIdentity generates a new ZeroTier Identity.
|
||||||
|
// This can be a little bit time consuming due to one way proof of work requirements (usually a few hundred milliseconds).
|
||||||
|
func NewIdentity() (id Identity) {
|
||||||
|
for {
|
||||||
|
pub, priv := generateDualPair()
|
||||||
|
dig := computeZeroTierIdentityMemoryHardHash(pub[:])
|
||||||
|
if dig[0] < ztIdentityHashCashFirstByteLessThan && dig[59] != 0xff {
|
||||||
|
addr := uint64(dig[59])
|
||||||
|
addr <<= 8
|
||||||
|
addr |= uint64(dig[60])
|
||||||
|
addr <<= 8
|
||||||
|
addr |= uint64(dig[61])
|
||||||
|
addr <<= 8
|
||||||
|
addr |= uint64(dig[62])
|
||||||
|
addr <<= 8
|
||||||
|
addr |= uint64(dig[63])
|
||||||
|
if addr != 0 {
|
||||||
|
id.Address = Address(addr)
|
||||||
|
id.PublicKey = pub[:]
|
||||||
|
id.privateKey = priv[:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, ":")
|
||||||
|
if len(ss) < 3 {
|
||||||
|
return nil, ErrInvalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var id Identity
|
||||||
|
id.Address, err = NewAddressFromString(ss[0])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ss[1] == "0" {
|
||||||
|
id.Type = 0
|
||||||
|
} else if ss[1] == "1" {
|
||||||
|
id.Type = 1
|
||||||
|
} else {
|
||||||
|
return nil, ErrUncrecognizedIdentityType
|
||||||
|
}
|
||||||
|
|
||||||
|
switch id.Type {
|
||||||
|
case 0:
|
||||||
|
id.PublicKey, err = hex.DecodeString(ss[2])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(ss) >= 4 {
|
||||||
|
id.privateKey, err = hex.DecodeString(ss[3])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return &id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasPrivate returns true if this identity has its own private portion.
|
||||||
|
func (id *Identity) HasPrivate() bool { return len(id.privateKey) > 0 }
|
||||||
|
|
||||||
|
// PrivateKeyString returns the full identity.secret if the private key is set, or an empty string if no private key is set.
|
||||||
|
func (id *Identity) PrivateKeyString() string {
|
||||||
|
if len(id.privateKey) == 64 {
|
||||||
|
s := fmt.Sprintf("%.10x:0:%x:%x", id.Address, id.PublicKey, id.privateKey)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKeyString returns the address and public key (identity.public contents).
|
||||||
|
// An empty string is returned if this identity is invalid or not initialized.
|
||||||
|
func (id *Identity) String() string {
|
||||||
|
if len(id.PublicKey) == 64 {
|
||||||
|
s := fmt.Sprintf("%.10x:0:%x", id.Address, id.PublicKey)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
|
@ -64,6 +64,11 @@ 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(path string) (*Node, error) {
|
func NewNode(path string) (*Node, error) {
|
||||||
|
os.MkdirAll(path, 0755)
|
||||||
|
if _, err := os.Stat(path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
n := new(Node)
|
n := new(Node)
|
||||||
n.path = path
|
n.path = path
|
||||||
n.networks = make(map[uint64]*Network)
|
n.networks = make(map[uint64]*Network)
|
||||||
|
@ -72,7 +77,7 @@ func NewNode(path string) (*Node, error) {
|
||||||
n.gn = C.ZT_GoNode_new(cpath)
|
n.gn = C.ZT_GoNode_new(cpath)
|
||||||
C.free(unsafe.Pointer(cpath))
|
C.free(unsafe.Pointer(cpath))
|
||||||
if n.gn == nil {
|
if n.gn == nil {
|
||||||
return nil, errors.New("unable to create new Node instance")
|
return nil, ErrNodeInitFailed
|
||||||
}
|
}
|
||||||
n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
|
n.zn = (*C.ZT_Node)(C.ZT_GoNode_getNode(n.gn))
|
||||||
|
|
||||||
|
@ -107,11 +112,11 @@ func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
|
||||||
n.networksLock.RUnlock()
|
n.networksLock.RUnlock()
|
||||||
|
|
||||||
if tap != nil {
|
if tap != nil {
|
||||||
return nil, errors.New("not implemented yet")
|
return nil, errors.New("non-native taps not implemented yet")
|
||||||
}
|
}
|
||||||
ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
|
ntap := C.ZT_GoNode_join(n.gn, C.uint64_t(nwid))
|
||||||
if ntap == nil {
|
if ntap == nil {
|
||||||
return nil, errors.New("unable to initialize native tap (check device driver or permissions)")
|
return nil, ErrTapInitFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
nw := &Network{
|
nw := &Network{
|
||||||
|
@ -133,6 +138,10 @@ func (n *Node) Join(nwid uint64, tap Tap) (*Network, error) {
|
||||||
|
|
||||||
// Leave leaves a network
|
// Leave leaves a network
|
||||||
func (n *Node) Leave(nwid uint64) error {
|
func (n *Node) Leave(nwid uint64) error {
|
||||||
|
C.ZT_GoNode_leave(n.gn, C.uint64_t(nwid))
|
||||||
|
n.networksLock.Lock()
|
||||||
|
delete(n.networks, nwid)
|
||||||
|
n.networksLock.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +166,7 @@ func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
|
||||||
secret = true
|
secret = true
|
||||||
case C.ZT_STATE_OBJECT_PEER:
|
case C.ZT_STATE_OBJECT_PEER:
|
||||||
fp = path.Join(n.path, "peers.d")
|
fp = path.Join(n.path, "peers.d")
|
||||||
os.Mkdir(fp, 0755)
|
os.Mkdir(fp, 0700)
|
||||||
fp = path.Join(fp, fmt.Sprintf("%.10x.peer", id[0]))
|
fp = path.Join(fp, fmt.Sprintf("%.10x.peer", id[0]))
|
||||||
secret = true
|
secret = true
|
||||||
case C.ZT_STATE_OBJECT_NETWORK_CONFIG:
|
case C.ZT_STATE_OBJECT_NETWORK_CONFIG:
|
||||||
|
@ -171,6 +180,7 @@ func (n *Node) makeStateObjectPath(objType int, id [2]uint64) (string, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
|
func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
|
||||||
|
go func() {
|
||||||
fp, secret := n.makeStateObjectPath(objType, id)
|
fp, secret := n.makeStateObjectPath(objType, id)
|
||||||
if len(fp) > 0 {
|
if len(fp) > 0 {
|
||||||
fileMode := os.FileMode(0644)
|
fileMode := os.FileMode(0644)
|
||||||
|
@ -182,13 +192,16 @@ func (n *Node) stateObjectPut(objType int, id [2]uint64, data []byte) {
|
||||||
acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
|
acl.Chmod(fp, 0600) // this emulates Unix chmod on Windows and uses os.Chmod on Unix-type systems
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
|
func (n *Node) stateObjectDelete(objType int, id [2]uint64) {
|
||||||
|
go func() {
|
||||||
fp, _ := n.makeStateObjectPath(objType, id)
|
fp, _ := n.makeStateObjectPath(objType, id)
|
||||||
if len(fp) > 0 {
|
if len(fp) > 0 {
|
||||||
os.Remove(fp)
|
os.Remove(fp)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
|
func (n *Node) stateObjectGet(objType int, id [2]uint64) ([]byte, bool) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue