Code formatting and other boring stuff.

This commit is contained in:
Adam Ierymenko 2020-06-01 15:40:00 -07:00
parent 1003455160
commit dc1ef0c49e
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
22 changed files with 503 additions and 349 deletions

View file

@ -53,6 +53,14 @@ Commands:
blacklist cidr <IP/bits> <boolean> Toggle physical path blacklisting
blacklist if <prefix> <boolean> Toggle interface prefix blacklisting
portmap <boolean> Toggle use of uPnP or NAT-PMP
controller <command> [option] Local controller management commands
networks List networks run by local controller
new Create a new network
set <network> [setting] [value] Show or modify network settings
members <network> List members of a network
member <network> [setting] [value] Show or modify member level settings
auth <address|fingerprint> Authorize a peer
deauth <address|fingerprint> Deauthorize a peer
identity <command> [args] Identity management commands
new [c25519|p384] Create identity pair (default: c25519)
getpublic <identity> Extract only public part of identity
@ -64,17 +72,8 @@ Commands:
show <locator> [identity] Show locator information
root [command] Root management commands
list List root peers (same as no command)
add <identity> <locator> Add or manually update a root
add <url> Add or update root(s) from a URL
add <identity> <endpoint|locator> Designate a peer as a root
remove <address> Un-designate a peer as a root
controller <command> [option] Local controller management commands
networks List networks run by local controller
new Create a new network
set <network> [setting] [value] Show or modify network settings
members <network> List members of a network
member <network> [setting] [value] Show or modify member level settings
auth <address|fingerprint> Authorize a peer
deauth <address|fingerprint> Deauthorize a peer
The 'service' command does not exit until the service receives a signal.
This is typically run from launchd (Mac), systemd or init (Linux), a Windows

View file

@ -10,7 +10,6 @@ import "C"
import (
"encoding/json"
"strings"
"unsafe"
)
@ -39,7 +38,6 @@ func NewEndpointFromString(s string) (*Endpoint, error) {
ep.cep._type = C.ZT_ENDPOINT_TYPE_NIL
return &ep, nil
}
if strings.IndexRune(s, '-') > 0 || (strings.IndexRune(s, ':') < 0 && strings.IndexRune(s, '.') < 0) {
var ep Endpoint
cs := C.CString(s)
defer C.free(unsafe.Pointer(cs))
@ -48,12 +46,6 @@ func NewEndpointFromString(s string) (*Endpoint, error) {
}
return &ep, nil
}
inaddr := NewInetAddressFromString(s)
if inaddr == nil {
return nil, ErrInvalidParameter
}
return NewEndpointFromInetAddress(inaddr)
}
func NewEndpointFromInetAddress(addr *InetAddress) (*Endpoint, error) {
var ep Endpoint

View file

@ -2123,11 +2123,30 @@ ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
/* ---------------------------------------------------------------------------------------------------------------- */
/**
* Convert an endpoint to a string
*
* @param ep Endpoint structure
* @param buf Buffer to store string (recommended size: 256)
* @param capacity Capacity of buffer
* @return String or NULL on error
*/
ZT_SDK_API char *ZT_Endpoint_toString(
const ZT_Endpoint *ep,
char *buf,
int capacity);
/**
* Parse an endpoint as a string
*
* This will automatically detect IP addresses in IP/port format. If one
* of these is specified rather than a fully specified endpoint it will be
* parsed as an IP/UDP endpoint.
*
* @param ep Endpoint structure to populate
* @param str String representation of endpoint
* @return OK (0) or error code
*/
ZT_SDK_API int ZT_Endpoint_fromString(
ZT_Endpoint *ep,
const char *str);

View file

@ -31,11 +31,23 @@ namespace ZeroTier {
class Address : public TriviallyCopyable
{
public:
ZT_INLINE Address() noexcept : _a(0) {}
ZT_INLINE Address(const uint64_t a) noexcept : _a(a) {}
explicit ZT_INLINE Address(const uint8_t b[5]) noexcept : _a(((uint64_t)b[0] << 32U) | ((uint64_t)b[1] << 24U) | ((uint64_t)b[2] << 16U) | ((uint64_t)b[3] << 8U) | (uint64_t)b[4]) {}
ZT_INLINE Address() noexcept:
_a(0)
{}
ZT_INLINE Address &operator=(const uint64_t a) noexcept { _a = a; return *this; }
ZT_INLINE Address(const uint64_t a) noexcept:
_a(a)
{}
explicit ZT_INLINE Address(const uint8_t b[5]) noexcept:
_a(((uint64_t) b[0] << 32U) | ((uint64_t) b[1] << 24U) | ((uint64_t) b[2] << 16U) | ((uint64_t) b[3] << 8U) | (uint64_t) b[4])
{}
ZT_INLINE Address &operator=(const uint64_t a) noexcept
{
_a = a;
return *this;
}
/**
* @param bits Raw address -- 5 bytes, big-endian byte order
@ -63,12 +75,14 @@ public:
/**
* @return Integer containing address (0 to 2^40)
*/
ZT_INLINE uint64_t toInt() const noexcept { return _a; }
ZT_INLINE uint64_t toInt() const noexcept
{ return _a; }
/**
* Set address to zero/NIL
*/
ZT_INLINE void zero() noexcept { _a = 0; }
ZT_INLINE void zero() noexcept
{ _a = 0; }
/**
* @param s String with at least 11 characters of space available (10 + terminating NULL)
@ -91,7 +105,13 @@ public:
s[10] = 0;
return s;
}
ZT_INLINE String toString() const { char s[ZT_ADDRESS_STRING_SIZE_MAX]; toString(s); return String(s); }
ZT_INLINE String toString() const
{
char s[ZT_ADDRESS_STRING_SIZE_MAX];
toString(s);
return String(s);
}
/**
* Check if this address is reserved
@ -102,26 +122,53 @@ public:
*
* @return True if address is reserved and may not be used
*/
ZT_INLINE bool isReserved() const noexcept { return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
ZT_INLINE bool isReserved() const noexcept
{ return ((!_a) || ((_a >> 32U) == ZT_ADDRESS_RESERVED_PREFIX)); }
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)_a; }
ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long) _a; }
ZT_INLINE operator bool() const noexcept { return (_a != 0); }
ZT_INLINE operator uint64_t() const noexcept { return _a; }
ZT_INLINE operator bool() const noexcept
{ return (_a != 0); }
ZT_INLINE bool operator==(const Address &a) const noexcept { return _a == a._a; }
ZT_INLINE bool operator!=(const Address &a) const noexcept { return _a != a._a; }
ZT_INLINE bool operator>(const Address &a) const noexcept { return _a > a._a; }
ZT_INLINE bool operator<(const Address &a) const noexcept { return _a < a._a; }
ZT_INLINE bool operator>=(const Address &a) const noexcept { return _a >= a._a; }
ZT_INLINE bool operator<=(const Address &a) const noexcept { return _a <= a._a; }
ZT_INLINE operator uint64_t() const noexcept
{ return _a; }
ZT_INLINE bool operator==(const uint64_t a) const noexcept { return _a == a; }
ZT_INLINE bool operator!=(const uint64_t a) const noexcept { return _a != a; }
ZT_INLINE bool operator>(const uint64_t a) const noexcept { return _a > a; }
ZT_INLINE bool operator<(const uint64_t a) const noexcept { return _a < a; }
ZT_INLINE bool operator>=(const uint64_t a) const noexcept { return _a >= a; }
ZT_INLINE bool operator<=(const uint64_t a) const noexcept { return _a <= a; }
ZT_INLINE bool operator==(const Address &a) const noexcept
{ return _a == a._a; }
ZT_INLINE bool operator!=(const Address &a) const noexcept
{ return _a != a._a; }
ZT_INLINE bool operator>(const Address &a) const noexcept
{ return _a > a._a; }
ZT_INLINE bool operator<(const Address &a) const noexcept
{ return _a < a._a; }
ZT_INLINE bool operator>=(const Address &a) const noexcept
{ return _a >= a._a; }
ZT_INLINE bool operator<=(const Address &a) const noexcept
{ return _a <= a._a; }
ZT_INLINE bool operator==(const uint64_t a) const noexcept
{ return _a == a; }
ZT_INLINE bool operator!=(const uint64_t a) const noexcept
{ return _a != a; }
ZT_INLINE bool operator>(const uint64_t a) const noexcept
{ return _a > a; }
ZT_INLINE bool operator<(const uint64_t a) const noexcept
{ return _a < a; }
ZT_INLINE bool operator>=(const uint64_t a) const noexcept
{ return _a >= a; }
ZT_INLINE bool operator<=(const uint64_t a) const noexcept
{ return _a <= a; }
private:
uint64_t _a;

View file

@ -84,6 +84,7 @@ class Buf
public:
// New and delete operators that allocate Buf instances from a shared lock-free memory pool.
static void *operator new(std::size_t sz);
static void operator delete(void *ptr);
/**
@ -114,12 +115,24 @@ public:
*/
struct Slice : TriviallyCopyable
{
ZT_INLINE Slice(const SharedPtr<Buf> &b_,const unsigned int s_,const unsigned int e_) noexcept : b(b_),s(s_),e(e_) {}
ZT_INLINE Slice() noexcept : b(),s(0),e(0) {}
ZT_INLINE Slice(const SharedPtr<Buf> &b_, const unsigned int s_, const unsigned int e_) noexcept: b(b_), s(s_), e(e_)
{}
ZT_INLINE operator bool() const noexcept { return (b); } // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
ZT_INLINE unsigned int size() const noexcept { return (e - s); }
ZT_INLINE void zero() noexcept { b.zero(); s = 0; e = 0; }
ZT_INLINE Slice() noexcept: b(), s(0), e(0)
{}
ZT_INLINE operator bool() const noexcept
{ return (b); }
ZT_INLINE unsigned int size() const noexcept
{ return (e - s); }
ZT_INLINE void zero() noexcept
{
b.zero();
s = 0;
e = 0;
}
/**
* Buffer holding slice data
@ -143,7 +156,8 @@ public:
class PacketVector : public ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS>
{
public:
ZT_INLINE PacketVector() : ZeroTier::FCV<Slice,ZT_MAX_PACKET_FRAGMENTS>() {}
ZT_INLINE PacketVector() : ZeroTier::FCV<Slice, ZT_MAX_PACKET_FRAGMENTS>()
{}
ZT_INLINE unsigned int totalSize() const noexcept
{
@ -218,19 +232,19 @@ public:
/**
* Create a new uninitialized buffer with undefined contents (use clear() to zero if needed)
*/
ZT_INLINE Buf() noexcept : __nextInPool(0),__refCount(0) {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
ZT_INLINE Buf() noexcept: __nextInPool(0), __refCount(0)
{}
/**
* Create a new buffer and copy data into it
*/
ZT_INLINE Buf(const void *const data,const unsigned int len) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
__nextInPool(0),
ZT_INLINE Buf(const void *const data, const unsigned int len) noexcept:
__refCount(0)
{
Utils::copy(unsafeData, data, len);
}
ZT_INLINE Buf(const Buf &b2) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init)
ZT_INLINE Buf(const Buf &b2) noexcept:
__nextInPool(0),
__refCount(0)
{
@ -253,7 +267,8 @@ public:
* @param ii Iterator to check
* @return True if iterator has read past the size of the buffer
*/
static ZT_INLINE bool writeOverflow(const int &ii) noexcept { return ((ii - ZT_BUF_MEM_SIZE) > 0); }
static ZT_INLINE bool writeOverflow(const int &ii) noexcept
{ return ((ii - ZT_BUF_MEM_SIZE) > 0); }
/**
* Check for overflow beyond the size of the data that should be in the buffer
@ -265,7 +280,8 @@ public:
* @param size Size of data that should be in buffer
* @return True if iterator has read past the size of the data
*/
static ZT_INLINE bool readOverflow(const int &ii,const unsigned int size) noexcept { return ((ii - (int)size) > 0); }
static ZT_INLINE bool readOverflow(const int &ii, const unsigned int size) noexcept
{ return ((ii - (int) size) > 0); }
/**
* Set all memory to zero
@ -837,7 +853,8 @@ public:
/**
* @return Capacity of this buffer (usable size of data.bytes)
*/
static constexpr unsigned int capacity() noexcept { return ZT_BUF_MEM_SIZE; }
static constexpr unsigned int capacity() noexcept
{ return ZT_BUF_MEM_SIZE; }
private:
// Next item in free buffer pool linked list if Buf is placed in pool, undefined and unused otherwise

View file

@ -137,7 +137,7 @@
/**
* Maximum number of queued endpoints to try per "pulse."
*/
#define ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE 16
#define ZT_NAT_T_PORT_SCAN_MAX 16
/**
* Delay between calls to the pulse() method in Peer for each peer

View file

@ -20,10 +20,6 @@
#include <string>
#include <memory>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
namespace ZeroTier {

View file

@ -97,7 +97,7 @@ public:
};
ZT_INLINE Defragmenter()
{} // NOLINT(hicpp-use-equals-default,modernize-use-equals-default)
{}
/**
* Process a fragment of a multi-part message

View file

@ -60,16 +60,20 @@ bool Endpoint::fromString(const char *s) noexcept
return true;
const char *start = strchr(s, '-');
if (start) {
if (start++ != nullptr) {
// Parse a fully qualified type-address format Endpoint.
char tmp[16];
for (unsigned int i = 0;i < 15;++i) {
if ((tmp[i] = s[i]) == 0)
for (unsigned int i=0;i<16;++i) {
char ss = s[i];
if (ss == '-') {
tmp[i] = 0;
break;
}
tmp[i] = ss;
}
tmp[15] = 0;
this->type = (ZT_EndpointType)Utils::strToUInt(tmp);
++start;
Fingerprint tmpfp;
MAC tmpmac;
switch (this->type) {
@ -93,10 +97,15 @@ bool Endpoint::fromString(const char *s) noexcept
if (!asInetAddress(this->value.ss).fromString(start))
return false;
default:
this->type = ZT_ENDPOINT_TYPE_NIL;
return false;
}
} else if ((strchr(s, ':')) || (strchr(s, '.'))) {
// Parse raw IP/port strings as IP_UDP endpoints.
this->type = ZT_ENDPOINT_TYPE_IP_UDP;
if (!asInetAddress(this->value.ss).fromString(s))
return false;
} else {
// A naked '0' can be a NIL endpoint.
if (Utils::strToUInt(s) != (unsigned int)ZT_ENDPOINT_TYPE_NIL)
return false;
}

View file

@ -77,7 +77,8 @@ public:
/**
* @return True if this ephemeral key has been initialized with generate()
*/
ZT_INLINE operator bool() const noexcept { return pub[0] != (uint8_t)TYPE_NIL; }
ZT_INLINE operator bool() const noexcept
{ return pub[0] != (uint8_t) TYPE_NIL; }
/**
* Generate or re-generate key pair.

View file

@ -39,7 +39,7 @@ namespace ZeroTier {
class Expect
{
public:
ZT_INLINE Expect() {} // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init,hicpp-use-equals-default,modernize-use-equals-default)
ZT_INLINE Expect() {}
/**
* Called by other code when something is sending a packet that could potentially receive an OK response

View file

@ -50,14 +50,16 @@ public:
*
* @param s Base32 string
*/
ZT_INLINE void toString(char s[ZT_FINGERPRINT_STRING_SIZE_MAX]) const noexcept
ZT_INLINE char *toString(char s[ZT_FINGERPRINT_STRING_SIZE_MAX]) const noexcept
{
Address(this->address).toString(s);
if (haveHash()) {
s[ZT_ADDRESS_LENGTH_HEX] = '-';
Utils::b32e(this->hash, ZT_FINGERPRINT_HASH_SIZE, s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_FINGERPRINT_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
}
return s;
}
ZT_INLINE String toString() const { char tmp[ZT_FINGERPRINT_STRING_SIZE_MAX]; return String(toString(tmp)); }
/**
* Set this fingerprint to a base32-encoded string

View file

@ -72,7 +72,7 @@ char *Locator::toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept
static_assert(ZT_LOCATOR_STRING_SIZE_MAX > ((((ZT_LOCATOR_MARSHAL_SIZE_MAX / 5) + 1) * 8) + ZT_ADDRESS_LENGTH_HEX + 1), "overflow");
uint8_t bin[ZT_LOCATOR_MARSHAL_SIZE_MAX];
Address(m_signer.address).toString(s);
s[ZT_ADDRESS_LENGTH_HEX] = '-';
s[ZT_ADDRESS_LENGTH_HEX] = '@';
Utils::b32e(bin, marshal(bin, false), s + (ZT_ADDRESS_LENGTH_HEX + 1), ZT_LOCATOR_STRING_SIZE_MAX - (ZT_ADDRESS_LENGTH_HEX + 1));
return s;
}

View file

@ -115,7 +115,9 @@ public:
* @return Pointer to buffer
*/
char *toString(char s[ZT_LOCATOR_STRING_SIZE_MAX]) const noexcept;
ZT_INLINE String toString() const { char tmp[ZT_LOCATOR_STRING_SIZE_MAX]; return String(toString(tmp)); }
ZT_INLINE String toString() const
{ char tmp[ZT_LOCATOR_STRING_SIZE_MAX]; return String(toString(tmp)); }
/**
* Decode a string format locator

View file

@ -28,7 +28,8 @@ namespace ZeroTier {
class MAC : public TriviallyCopyable
{
public:
ZT_INLINE MAC() noexcept : m_mac(0ULL) {}
ZT_INLINE MAC() noexcept: m_mac(0ULL)
{}
ZT_INLINE MAC(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d, const uint8_t e, const uint8_t f) noexcept:
m_mac((((uint64_t) a) << 40U) | (((uint64_t) b) << 32U) | (((uint64_t) c) << 24U) | (((uint64_t) d) << 16U) | (((uint64_t) e) << 8U) | ((uint64_t) f))
@ -47,12 +48,14 @@ public:
/**
* @return MAC in 64-bit integer
*/
ZT_INLINE uint64_t toInt() const noexcept { return m_mac; }
ZT_INLINE uint64_t toInt() const noexcept
{ return m_mac; }
/**
* Set MAC to zero
*/
ZT_INLINE void zero() noexcept { m_mac = 0ULL; }
ZT_INLINE void zero() noexcept
{ m_mac = 0ULL; }
/**
* @param bits Raw MAC in big-endian byte order
@ -80,12 +83,14 @@ public:
/**
* @return True if this is broadcast (all 0xff)
*/
ZT_INLINE bool isBroadcast() const noexcept { return m_mac; }
ZT_INLINE bool isBroadcast() const noexcept
{ return m_mac; }
/**
* @return True if this is a multicast MAC
*/
ZT_INLINE bool isMulticast() const noexcept { return ((m_mac & 0x010000000000ULL) != 0ULL); }
ZT_INLINE bool isMulticast() const noexcept
{ return ((m_mac & 0x010000000000ULL) != 0ULL); }
/**
* Set this MAC to a MAC derived from an address and a network ID
@ -137,17 +142,23 @@ public:
* @param i Value from 0 to 5 (inclusive)
* @return Byte at said position (address interpreted in big-endian order)
*/
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept { return (uint8_t)(m_mac >> (unsigned int)(40 - (i * 8))); }
ZT_INLINE uint8_t operator[](unsigned int i) const noexcept
{ return (uint8_t)(m_mac >> (unsigned int) (40 - (i * 8))); }
/**
* @return 6, which is the number of bytes in a MAC, for container compliance
*/
ZT_INLINE unsigned int size() const noexcept { return 6; }
ZT_INLINE unsigned int size() const noexcept
{ return 6; }
ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)Utils::hash64(m_mac); }
ZT_INLINE unsigned long hashCode() const noexcept
{ return (unsigned long) Utils::hash64(m_mac); }
ZT_INLINE operator bool() const noexcept { return (m_mac != 0ULL); }
ZT_INLINE operator uint64_t() const noexcept { return m_mac; }
ZT_INLINE operator bool() const noexcept
{ return (m_mac != 0ULL); }
ZT_INLINE operator uint64_t() const noexcept
{ return m_mac; }
/**
* Convert this MAC to a standard format colon-separated hex string
@ -177,7 +188,9 @@ public:
buf[17] = (char) 0;
return buf;
}
ZT_INLINE String toString() const { char tmp[18]; return String(toString(tmp)); }
ZT_INLINE String toString() const
{ char tmp[18]; return String(toString(tmp)); }
/**
* Parse a MAC address in hex format with or without : separators and ignoring non-hex characters.
@ -204,21 +217,47 @@ public:
}
}
ZT_INLINE MAC &operator=(const uint64_t m) noexcept { m_mac = m; return *this; }
ZT_INLINE MAC &operator=(const uint64_t m) noexcept
{
m_mac = m;
return *this;
}
ZT_INLINE bool operator==(const MAC &m) const noexcept { return (m_mac == m.m_mac); }
ZT_INLINE bool operator!=(const MAC &m) const noexcept { return (m_mac != m.m_mac); }
ZT_INLINE bool operator<(const MAC &m) const noexcept { return (m_mac < m.m_mac); }
ZT_INLINE bool operator<=(const MAC &m) const noexcept { return (m_mac <= m.m_mac); }
ZT_INLINE bool operator>(const MAC &m) const noexcept { return (m_mac > m.m_mac); }
ZT_INLINE bool operator>=(const MAC &m) const noexcept { return (m_mac >= m.m_mac); }
ZT_INLINE bool operator==(const MAC &m) const noexcept
{ return (m_mac == m.m_mac); }
ZT_INLINE bool operator==(const uint64_t m) const noexcept { return (m_mac == m); }
ZT_INLINE bool operator!=(const uint64_t m) const noexcept { return (m_mac != m); }
ZT_INLINE bool operator<(const uint64_t m) const noexcept { return (m_mac < m); }
ZT_INLINE bool operator<=(const uint64_t m) const noexcept { return (m_mac <= m); }
ZT_INLINE bool operator>(const uint64_t m) const noexcept { return (m_mac > m); }
ZT_INLINE bool operator>=(const uint64_t m) const noexcept { return (m_mac >= m); }
ZT_INLINE bool operator!=(const MAC &m) const noexcept
{ return (m_mac != m.m_mac); }
ZT_INLINE bool operator<(const MAC &m) const noexcept
{ return (m_mac < m.m_mac); }
ZT_INLINE bool operator<=(const MAC &m) const noexcept
{ return (m_mac <= m.m_mac); }
ZT_INLINE bool operator>(const MAC &m) const noexcept
{ return (m_mac > m.m_mac); }
ZT_INLINE bool operator>=(const MAC &m) const noexcept
{ return (m_mac >= m.m_mac); }
ZT_INLINE bool operator==(const uint64_t m) const noexcept
{ return (m_mac == m); }
ZT_INLINE bool operator!=(const uint64_t m) const noexcept
{ return (m_mac != m); }
ZT_INLINE bool operator<(const uint64_t m) const noexcept
{ return (m_mac < m); }
ZT_INLINE bool operator<=(const uint64_t m) const noexcept
{ return (m_mac <= m); }
ZT_INLINE bool operator>(const uint64_t m) const noexcept
{ return (m_mac > m); }
ZT_INLINE bool operator>=(const uint64_t m) const noexcept
{ return (m_mac >= m); }
private:
uint64_t m_mac;

View file

@ -79,6 +79,8 @@ Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, in
m_now(now),
m_online(false)
{
ZT_SPEW("starting up...");
// Load this node's identity.
uint64_t idtmp[2];
idtmp[0] = 0;
@ -91,6 +93,7 @@ Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, in
RR->identity.toString(false, RR->publicIdentityStr);
RR->identity.toString(true, RR->secretIdentityStr);
haveIdentity = true;
ZT_SPEW("loaded identity %s", RR->identity.toString().c_str());
}
}
@ -103,6 +106,7 @@ Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, in
idtmp[1] = 0;
stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, idtmp, RR->secretIdentityStr, (unsigned int)strlen(RR->secretIdentityStr));
stateObjectPut(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, idtmp, RR->publicIdentityStr, (unsigned int)strlen(RR->publicIdentityStr));
ZT_SPEW("no pre-existing identity found, created %s", RR->identity.toString().c_str());
} else {
idtmp[0] = RR->identity.address();
idtmp[1] = 0;
@ -136,13 +140,16 @@ Node::Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, in
// This constructs all the components of the ZeroTier core within a single contiguous memory container,
// which reduces memory fragmentation and may improve cache locality.
ZT_SPEW("initializing subsystem objects...");
m_objects = new _NodeObjects(RR, tPtr);
ZT_SPEW("node initialized!");
postEvent(tPtr, ZT_EVENT_UP);
}
Node::~Node()
{
ZT_SPEW("node destructor run");
m_networks_l.lock();
m_networks_l.unlock();
m_networks.clear();
@ -161,6 +168,7 @@ Node::~Node()
void Node::shutdown(void *tPtr)
{
ZT_SPEW("explicit shutdown() called");
postEvent(tPtr, ZT_EVENT_DOWN);
if (RR->topology)
RR->topology->saveAll(tPtr);
@ -202,25 +210,6 @@ ZT_ResultCode Node::processVirtualNetworkFrame(
}
}
struct _processBackgroundTasks_eachPeer
{
const int64_t now;
void *const tPtr;
bool online;
ZT_INLINE _processBackgroundTasks_eachPeer(const int64_t now_, void *const tPtr_) noexcept :
now(now_),
tPtr(tPtr_),
online(false)
{}
ZT_INLINE void operator()(const SharedPtr<Peer> &peer, const bool isRoot) noexcept
{
peer->pulse(tPtr, now, isRoot);
this->online |= (isRoot && peer->directlyConnected(now));
}
};
ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline)
{
m_now = now;
@ -230,14 +219,22 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
// Call peer pulse() method of all peers every ZT_PEER_PULSE_INTERVAL.
if ((now - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) {
m_lastPeerPulse = now;
ZT_SPEW("running pulse() on each peer...");
try {
_processBackgroundTasks_eachPeer pf(now, tPtr);
RR->topology->eachPeerWithRoot<_processBackgroundTasks_eachPeer &>(pf);
Vector< SharedPtr<Peer> > allPeers, rootPeers;
RR->topology->getAllPeers(allPeers, rootPeers);
if (m_online.exchange(pf.online) != pf.online)
postEvent(tPtr, pf.online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
bool online = false;
for(Vector< SharedPtr<Peer> >::iterator p(allPeers.begin());p!=allPeers.end();++p) {
const bool isRoot = std::find(rootPeers.begin(), rootPeers.end(), *p) != rootPeers.end();
(*p)->pulse(tPtr, now, isRoot);
online |= ((isRoot || rootPeers.empty()) && (*p)->directlyConnected(now));
}
RR->topology->rankRoots();
if (m_online.exchange(online) != online)
postEvent(tPtr, online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE);
} catch (...) {
return ZT_RESULT_FATAL_ERROR_INTERNAL;
}
@ -246,6 +243,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
// Perform network housekeeping and possibly request new certs and configs every ZT_NETWORK_HOUSEKEEPING_PERIOD.
if ((now - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) {
m_lastHousekeepingRun = now;
ZT_SPEW("running networking housekeeping...");
RWMutex::RLock l(m_networks_l);
for (Map<uint64_t, SharedPtr<Network> >::const_iterator i(m_networks.begin());i != m_networks.end();++i) {
i->second->doPeriodicTasks(tPtr, now);
@ -255,6 +253,7 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
// Clean up other stuff every ZT_HOUSEKEEPING_PERIOD.
if ((now - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) {
m_lastHousekeepingRun = now;
ZT_SPEW("running housekeeping...");
// Clean up any old local controller auth memoizations. This is an
// optimization for network controllers to know whether to accept
@ -282,8 +281,12 @@ ZT_ResultCode Node::processBackgroundTasks(void *tPtr, int64_t now, volatile int
ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, void *tptr)
{
Fingerprint fp;
if (controllerFingerprint)
if (controllerFingerprint) {
fp = *controllerFingerprint;
ZT_SPEW("joining network %.16llx with fingerprint %s",nwid,fp.toString().c_str());
} else {
ZT_SPEW("joining network %.16llx",nwid);
}
RWMutex::Lock l(m_networks_l);
SharedPtr<Network> &nw = m_networks[nwid];
@ -296,6 +299,7 @@ ZT_ResultCode Node::join(uint64_t nwid, const ZT_Fingerprint *controllerFingerpr
ZT_ResultCode Node::leave(uint64_t nwid, void **uptr, void *tptr)
{
ZT_SPEW("leaving network %.16llx",nwid);
ZT_VirtualNetworkConfig ctmp;
m_networks_l.lock();
@ -327,6 +331,7 @@ ZT_ResultCode Node::leave(uint64_t nwid, void **uptr, void *tptr)
ZT_ResultCode Node::multicastSubscribe(void *tPtr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
{
ZT_SPEW("multicast subscribe to %s:%lu",MAC(multicastGroup).toString().c_str(),multicastAdi);
const SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastSubscribe(tPtr, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));
@ -336,6 +341,7 @@ ZT_ResultCode Node::multicastSubscribe(void *tPtr, uint64_t nwid, uint64_t multi
ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi)
{
ZT_SPEW("multicast unsubscribe from %s:%lu",MAC(multicastGroup).toString().c_str(),multicastAdi);
const SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastUnsubscribe(MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff)));

View file

@ -202,7 +202,7 @@ public:
* @param nwid Network ID
* @return Network associated with ID
*/
ZT_INLINE SharedPtr<Network> network(uint64_t nwid) const noexcept
ZT_INLINE SharedPtr<Network> network(const uint64_t nwid) const noexcept
{
RWMutex::RLock l(m_networks_l);
const SharedPtr<Network> *const n = m_networks.get(nwid);

View file

@ -199,9 +199,10 @@ typedef unsigned uint128_t __attribute__((mode(TI)));
#endif
// Macro to print very verbose tracing information to standard error.
#define ZT_VA_ARGS(...) , ##__VA_ARGS__
#define ZT_DEBUG_SPEW
#ifdef ZT_DEBUG_SPEW
#define ZT_SPEW(f,...) fprintf(stderr,"%s:%d(%s): " f ZT_EOL_S,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__)
#define ZT_SPEW(f,...) fprintf(stderr,"%s:%d(%s): " f ZT_EOL_S,__FILE__,__LINE__,__FUNCTION__ ZT_VA_ARGS(__VA_ARGS__))
#else
#define ZT_SPEW(f,...)
#endif

View file

@ -213,9 +213,7 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA
p1305.finish(polyMac);
Utils::storeAsIsEndian<uint64_t>(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]);
if (likely(RR->node->putPacket(tPtr, localSocket, atAddress, outp.unsafeData, ii)))
return ii;
return 0;
return (likely(RR->node->putPacket(tPtr, localSocket, atAddress, outp.unsafeData, ii))) ? ii : 0;
}
void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
@ -263,47 +261,83 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
// Attempt up to ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE queued addresses.
unsigned int attempts = 0;
do {
for(;;) {
p_TryQueueItem &qi = m_tryQueue.front();
if (qi.target.isInetAddr()) {
// Skip entry if it overlaps with any currently active IP.
for (unsigned int i = 0;i < m_alivePathCount;++i) {
if (m_paths[i]->address().ipsEqual(qi.target.ip()))
goto next_tryQueue_item;
goto discard_queue_item;
}
}
if (qi.target.type == ZT_ENDPOINT_TYPE_IP_UDP) {
++attempts;
if (qi.privilegedPortTrialIteration < 0) {
if (qi.iteration < 0) {
// If iteration is less than zero, try to contact the original address.
// It may be set to a larger negative value to try multiple times such
// as e.g. -3 to try 3 times.
sent(now, m_sendProbe(tPtr, -1, qi.target.ip(), nullptr, 0, now));
if ((qi.target.ip().isV4()) && (qi.target.ip().port() < 1024)) {
qi.privilegedPortTrialIteration = 0;
if (m_tryQueue.size() > 1)
m_tryQueue.splice(m_tryQueue.end(),m_tryQueue,m_tryQueue.begin());
continue;
} // else goto next_tryQueue_item;
} else if (qi.privilegedPortTrialIteration < 1023) {
uint16_t ports[ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE];
++qi.iteration;
goto requeue_item;
} else if (qi.target.ip().isV4() && (m_alivePathCount == 0)) {
// When iteration reaches zero the queue item is dropped unless it's
// IPv4 and we have no direct paths. In that case some heavier NAT-t
// strategies are attempted.
if (qi.target.ip().port() < 1024) {
// If the source port is privileged, we actually scan every possible
// privileged port in random order slowly over multiple iterations
// of pulse(). This is done in batches of ZT_NAT_T_PORT_SCAN_MAX.
uint16_t ports[ZT_NAT_T_PORT_SCAN_MAX];
unsigned int pn = 0;
while ((pn < ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE) && (qi.privilegedPortTrialIteration < 1023)) {
const uint16_t p = RR->randomPrivilegedPortOrder[qi.privilegedPortTrialIteration++];
while ((pn < ZT_NAT_T_PORT_SCAN_MAX) && (qi.iteration < 1023)) {
const uint16_t p = RR->randomPrivilegedPortOrder[qi.iteration++];
if ((unsigned int)p != qi.target.ip().port())
ports[pn++] = p;
}
if (pn > 0)
sent(now, m_sendProbe(tPtr, -1, qi.target.ip(), ports, pn, now));
if (qi.privilegedPortTrialIteration < 1023) {
if (m_tryQueue.size() > 1)
m_tryQueue.splice(m_tryQueue.end(),m_tryQueue,m_tryQueue.begin());
continue;
} // else goto next_tryQueue_item;
if (qi.iteration < 1023)
goto requeue_item;
} else {
// For un-privileged ports we'll try ZT_NAT_T_PORT_SCAN_MAX ports
// beyond the one we were sent to catch some sequentially assigning
// symmetric NATs.
InetAddress tmp(qi.target.ip());
unsigned int p = tmp.port() + 1 + (unsigned int)qi.iteration++;
if (p > 65535)
p -= 64512; // wrap back to 1024
tmp.setPort(p);
sent(now, m_sendProbe(tPtr, -1, tmp, nullptr, 0, now));
if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX)
goto requeue_item;
}
}
}
next_tryQueue_item:
// Discard front item unless the code skips to requeue_item.
discard_queue_item:
m_tryQueue.pop_front();
} while ((attempts < ZT_NAT_T_MAX_QUEUED_ATTEMPTS_PER_PULSE) && (!m_tryQueue.empty()));
if ((m_tryQueue.empty()) || (attempts >= ZT_NAT_T_PORT_SCAN_MAX))
break;
else continue;
// If the code skips here the front item is instead moved to the back.
requeue_item:
if (m_tryQueue.size() > 1)
m_tryQueue.splice(m_tryQueue.end(), m_tryQueue, m_tryQueue.begin());
if (attempts >= ZT_NAT_T_PORT_SCAN_MAX)
break;
else continue;
}
}
// Do keepalive on all currently active paths, sending HELLO to the first
@ -338,7 +372,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot)
}
}
void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep)
void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries)
{
static uint8_t foo = 0;
RWMutex::Lock l(m_lock);
@ -364,12 +398,12 @@ void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep)
for (List<p_TryQueueItem>::iterator i(m_tryQueue.begin());i != m_tryQueue.end();++i) {
if (i->target.isSameAddress(ep)) {
i->target = ep;
i->privilegedPortTrialIteration = -1;
i->iteration = -tries;
return;
}
}
m_tryQueue.push_back(p_TryQueueItem(ep));
m_tryQueue.push_back(p_TryQueueItem(ep, -tries));
}
void Peer::resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now)

View file

@ -231,8 +231,9 @@ public:
* @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call
* @param now Current time
* @param ep Endpoint to attempt to contact
* @param tries Number of times to try (default: 1)
*/
void contact(void *tPtr, int64_t now, const Endpoint &ep);
void contact(void *tPtr, int64_t now, const Endpoint &ep, int tries = 1);
/**
* Reset paths within a given IP scope and address family
@ -525,16 +526,16 @@ private:
{
ZT_INLINE p_TryQueueItem() :
target(),
privilegedPortTrialIteration(-1)
iteration(0)
{}
ZT_INLINE p_TryQueueItem(const Endpoint &t) :
ZT_INLINE p_TryQueueItem(const Endpoint &t, int iter) :
target(t),
privilegedPortTrialIteration(-1)
iteration(iter)
{}
Endpoint target;
int privilegedPortTrialIteration;
int iteration;
};
List<p_TryQueueItem> m_tryQueue;

View file

@ -147,39 +147,28 @@ public:
}
/**
* Apply a function or function object to all peers
*
* This locks the peer map during execution, so calls to get() etc. during
* eachPeer() will deadlock.
*
* @param f Function to apply
* @tparam F Function or function object type
* @param allPeers vector to fill with all current peers
*/
template<typename F>
ZT_INLINE void eachPeerWithRoot(F f) const
ZT_INLINE void getAllPeers(Vector< SharedPtr<Peer> > &allPeers) const
{
allPeers.clear();
RWMutex::RLock l(m_peers_l);
Vector<uintptr_t> rootPeerPtrs;
rootPeerPtrs.reserve(m_rootPeers.size());
for(Vector< SharedPtr<Peer> >::const_iterator rp(m_rootPeers.begin());rp != m_rootPeers.end();++rp)
rootPeerPtrs.push_back((uintptr_t)rp->ptr());
std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end());
allPeers.reserve(m_peers.size());
for(Map< Address,SharedPtr<Peer> >::const_iterator i(m_peers.begin());i != m_peers.end();++i)
f(i->second,std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)i->second.ptr()));
allPeers.push_back(i->second);
}
/**
* @param allPeers vector to fill with all current peers
*/
ZT_INLINE void getAllPeers(Vector< SharedPtr<Peer> > &allPeers) const
ZT_INLINE void getAllPeers(Vector< SharedPtr<Peer> > &allPeers,Vector< SharedPtr<Peer> > &rootPeers) const
{
RWMutex::RLock l(m_peers_l);
allPeers.clear();
RWMutex::RLock l(m_peers_l);
allPeers.reserve(m_peers.size());
for(Map< Address,SharedPtr<Peer> >::const_iterator i(m_peers.begin());i != m_peers.end();++i)
allPeers.push_back(i->second);
rootPeers = m_rootPeers;
}
/**