diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a2102da8..7218a6ea3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,7 @@ if(NOT PACKAGE_STATIC) -Wno-deprecated -Wno-unused-function -Wno-format + -Wno-attributes $<$:-g> $<$:-O0> $<$:-O3> @@ -125,6 +126,7 @@ if(NOT PACKAGE_STATIC) -Wall -Wno-deprecated -Wno-unused-function + -Wno-attributes -mmacosx-version-min=${MACOS_VERSION_MIN} $<$:-g> $<$:-O0> @@ -157,6 +159,7 @@ if(NOT PACKAGE_STATIC) -Wno-deprecated -Wno-unused-function -Wno-format + -Wno-attributes $<$:-g> $<$:-O0> $<$:-O3> diff --git a/core/Buf.cpp b/core/Buf.cpp index cb5c5b182..a9b94777d 100644 --- a/core/Buf.cpp +++ b/core/Buf.cpp @@ -12,15 +12,12 @@ /****/ #include "Buf.hpp" - -#ifdef __WINDOWS__ -#define sched_yield() Sleep(0) -#endif +#include "Spinlock.hpp" namespace ZeroTier { -static std::atomic s_pool(0); -static std::atomic s_allocated(0); +static std::atomic< uintptr_t > s_pool(0); +static std::atomic< long > s_allocated(0); // uintptr_max can never be a valid pointer, so use it to indicate that s_pool is locked (very short duration spinlock) #define ZT_ATOMIC_PTR_LOCKED (~((uintptr_t)0)) @@ -29,45 +26,44 @@ void *Buf::operator new(std::size_t sz) { uintptr_t bb; for (;;) { - bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); - if (bb != ZT_ATOMIC_PTR_LOCKED) + bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire); + if (likely(bb != ZT_ATOMIC_PTR_LOCKED)) break; - sched_yield(); + Spinlock::pause(); } Buf *b; if (bb) { - s_pool.store(((Buf *) bb)->__nextInPool); - b = (Buf *) bb; + s_pool.store(((Buf *)bb)->__nextInPool.load(std::memory_order_relaxed), std::memory_order_release); + b = (Buf *)bb; } else { - s_pool.store(0); - b = (Buf *) malloc(sz); + s_pool.store(0, std::memory_order_release); + b = (Buf *)malloc(sz); if (!b) throw Utils::BadAllocException; - ++s_allocated; + s_allocated.fetch_add(1, std::memory_order_relaxed); } - b->__refCount.store(0); - return (void *) b; + b->__refCount.store(0, std::memory_order_relaxed); + return (void *)b; } void Buf::operator delete(void *ptr) { if (ptr) { - if (s_allocated.load() > ZT_BUF_MAX_POOL_SIZE) { - --s_allocated; + if (s_allocated.load(std::memory_order_relaxed) > ZT_BUF_MAX_POOL_SIZE) { free(ptr); } else { uintptr_t bb; for (;;) { - bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); - if (bb != ZT_ATOMIC_PTR_LOCKED) + bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire); + if (likely(bb != ZT_ATOMIC_PTR_LOCKED)) break; - sched_yield(); + Spinlock::pause(); } - ((Buf *) ptr)->__nextInPool.store(bb); - s_pool.store((uintptr_t) ptr); + ((Buf *)ptr)->__nextInPool.store(bb, std::memory_order_relaxed); + s_pool.store((uintptr_t)ptr, std::memory_order_release); } } } @@ -76,24 +72,23 @@ void Buf::freePool() noexcept { uintptr_t bb; for (;;) { - bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED); - if (bb != ZT_ATOMIC_PTR_LOCKED) + bb = s_pool.exchange(ZT_ATOMIC_PTR_LOCKED, std::memory_order_acquire); + if (likely(bb != ZT_ATOMIC_PTR_LOCKED)) break; - sched_yield(); + Spinlock::pause(); } - s_pool.store(0); + + s_pool.store(0, std::memory_order_release); while (bb != 0) { - const uintptr_t next = ((Buf *) bb)->__nextInPool; - --s_allocated; - free((void *) bb); + const uintptr_t next = ((Buf *)bb)->__nextInPool.load(std::memory_order_relaxed); + s_allocated.fetch_sub(1, std::memory_order_relaxed); + free((void *)bb); bb = next; } } long Buf::poolAllocated() noexcept -{ - return s_allocated.load(); -} +{ return s_allocated.load(std::memory_order_relaxed); } } // namespace ZeroTier diff --git a/core/Buf.hpp b/core/Buf.hpp index 69dd93f4a..d209a2ae8 100644 --- a/core/Buf.hpp +++ b/core/Buf.hpp @@ -286,7 +286,7 @@ public: /** * Set all memory to zero */ - ZT_INLINE void clear() noexcept + ZT_MAYBE_UNUSED ZT_INLINE void clear() noexcept { Utils::zero< ZT_BUF_MEM_SIZE >(unsafeData); } @@ -297,7 +297,7 @@ public: * @param ii Index value-result parameter (incremented by 1) * @return Byte (undefined on overflow) */ - ZT_INLINE uint8_t rI8(int &ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t rI8(int &ii) const noexcept { const int s = ii++; return unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK]; @@ -309,7 +309,7 @@ public: * @param ii Index value-result parameter (incremented by 2) * @return Integer (undefined on overflow) */ - ZT_INLINE uint16_t rI16(int &ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint16_t rI16(int &ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; ii += 2; @@ -328,7 +328,7 @@ public: * @param ii Index value-result parameter (incremented by 4) * @return Integer (undefined on overflow) */ - ZT_INLINE uint32_t rI32(int &ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint32_t rI32(int &ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; ii += 4; @@ -349,7 +349,7 @@ public: * @param ii Index value-result parameter (incremented by 8) * @return Integer (undefined on overflow) */ - ZT_INLINE uint64_t rI64(int &ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint64_t rI64(int &ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; ii += 8; @@ -384,7 +384,7 @@ public: * @return Bytes read or a negative value on unmarshal error (passed from object) or overflow */ template< typename T > - ZT_INLINE int rO(int &ii, T &obj) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE int rO(int &ii, T &obj) const noexcept { if (likely(ii < ZT_BUF_MEM_SIZE)) { int ms = obj.unmarshal(unsafeData + ii, ZT_BUF_MEM_SIZE - ii); @@ -406,7 +406,7 @@ public: * @param bufSize Capacity of buffer in bytes * @return Pointer to buf or NULL on overflow or error */ - ZT_INLINE char *rS(int &ii, char *const buf, const unsigned int bufSize) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE char *rS(int &ii, char *const buf, const unsigned int bufSize) const noexcept { const char *const s = (const char *)(unsafeData + ii); const int sii = ii; @@ -435,7 +435,7 @@ public: * @param ii Index value-result parameter (incremented by length of string) * @return Pointer to null-terminated C-style string or NULL on overflow or error */ - ZT_INLINE const char *rSnc(int &ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const char *rSnc(int &ii) const noexcept { const char *const s = (const char *)(unsafeData + ii); while (ii < ZT_BUF_MEM_SIZE) { @@ -456,7 +456,7 @@ public: * @param len Length of buffer * @return Pointer to data or NULL on overflow or error */ - ZT_INLINE uint8_t *rB(int &ii, void *const bytes, const unsigned int len) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t *rB(int &ii, void *const bytes, const unsigned int len) const noexcept { if (likely(((ii += (int)len) <= ZT_BUF_MEM_SIZE))) { Utils::copy(bytes, unsafeData + ii, len); @@ -478,7 +478,7 @@ public: * @param len Length of data field to obtain a pointer to * @return Pointer to field or NULL on overflow */ - ZT_INLINE const uint8_t *rBnc(int &ii, unsigned int len) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const uint8_t *rBnc(int &ii, unsigned int len) const noexcept { const uint8_t *const b = unsafeData + ii; return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr; @@ -491,7 +491,7 @@ public: * @return Value */ template< unsigned int I > - ZT_INLINE uint8_t lI8() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI8() const noexcept { static_assert(I < ZT_BUF_MEM_SIZE, "overflow"); return unsafeData[I]; @@ -504,7 +504,7 @@ public: * @return Value */ template< unsigned int I > - ZT_INLINE uint8_t lI16() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI16() const noexcept { static_assert((I + 1) < ZT_BUF_MEM_SIZE, "overflow"); #ifdef ZT_NO_UNALIGNED_ACCESS @@ -523,7 +523,7 @@ public: * @return Value */ template< unsigned int I > - ZT_INLINE uint8_t lI32() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI32() const noexcept { static_assert((I + 3) < ZT_BUF_MEM_SIZE, "overflow"); #ifdef ZT_NO_UNALIGNED_ACCESS @@ -544,7 +544,7 @@ public: * @return Value */ template< unsigned int I > - ZT_INLINE uint8_t lI64() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI64() const noexcept { static_assert((I + 7) < ZT_BUF_MEM_SIZE, "overflow"); #ifdef ZT_NO_UNALIGNED_ACCESS @@ -569,7 +569,7 @@ public: * will not necessarily result in a 'true' return from readOverflow(). It does * however subject 'ii' to soft bounds masking like the gI??() methods. */ - ZT_INLINE uint8_t lI8(const int ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI8(const int ii) const noexcept { return unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK]; } @@ -581,7 +581,7 @@ public: * will not necessarily result in a 'true' return from readOverflow(). It does * however subject 'ii' to soft bounds masking like the gI??() methods. */ - ZT_INLINE uint16_t lI16(const int ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint16_t lI16(const int ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -600,7 +600,7 @@ public: * will not necessarily result in a 'true' return from readOverflow(). It does * however subject 'ii' to soft bounds masking like the gI??() methods. */ - ZT_INLINE uint32_t lI32(const int ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint32_t lI32(const int ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -621,7 +621,7 @@ public: * will not necessarily result in a 'true' return from readOverflow(). It does * however subject 'ii' to soft bounds masking like the gI??() methods. */ - ZT_INLINE uint8_t lI64(const int ii) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE uint8_t lI64(const int ii) const noexcept { const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -645,7 +645,7 @@ public: * @param ii Index value-result parameter (incremented by 1) * @param n Byte */ - ZT_INLINE void wI8(int &ii, const uint8_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wI8(int &ii, const uint8_t n) noexcept { const int s = ii++; unsafeData[(unsigned int)s & ZT_BUF_MEM_MASK] = n; @@ -657,7 +657,7 @@ public: * @param ii Index value-result parameter (incremented by 2) * @param n Integer */ - ZT_INLINE void wI16(int &ii, const uint16_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wI16(int &ii, const uint16_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; ii += 2; @@ -675,7 +675,7 @@ public: * @param ii Index value-result parameter (incremented by 4) * @param n Integer */ - ZT_INLINE void wI32(int &ii, const uint32_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wI32(int &ii, const uint32_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; ii += 4; @@ -695,7 +695,7 @@ public: * @param ii Index value-result parameter (incremented by 8) * @param n Integer */ - ZT_INLINE void wI64(int &ii, const uint64_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wI64(int &ii, const uint64_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; ii += 8; @@ -721,7 +721,7 @@ public: * @param t Object to write */ template< typename T > - ZT_INLINE void wO(int &ii, T &t) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wO(int &ii, T &t) noexcept { const int s = ii; if (likely((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE)) { @@ -739,7 +739,7 @@ public: * @param ii Index value-result parameter (incremented by length of string) * @param s String to write (writes an empty string if this is NULL) */ - ZT_INLINE void wS(int &ii, const char *s) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wS(int &ii, const char *s) noexcept { if (s) { char c; @@ -759,7 +759,7 @@ public: * @param bytes Bytes to write * @param len Size of data in bytes */ - ZT_INLINE void wB(int &ii, const void *const bytes, const unsigned int len) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wB(int &ii, const void *const bytes, const unsigned int len) noexcept { const int s = ii; if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) @@ -772,7 +772,7 @@ public: * @param ii Index value-result parameter (incremented by len) * @param len Number of zero bytes to write */ - ZT_INLINE void wZ(int &ii, const unsigned int len) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wZ(int &ii, const unsigned int len) noexcept { const int s = ii; if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) @@ -785,7 +785,7 @@ public: * @param ii Index value-result parameter (incremented by len) * @param len Number of random bytes to write */ - ZT_INLINE void wR(int &ii, const unsigned int len) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void wR(int &ii, const unsigned int len) noexcept { const int s = ii; if (likely((ii += (int)len) <= ZT_BUF_MEM_SIZE)) @@ -795,7 +795,7 @@ public: /** * Store a byte without advancing the index */ - ZT_INLINE void sI8(const int ii, const uint8_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void sI8(const int ii, const uint8_t n) noexcept { unsafeData[(unsigned int)ii & ZT_BUF_MEM_MASK] = n; } @@ -803,7 +803,7 @@ public: /** * Store an integer without advancing the index */ - ZT_INLINE void sI16(const int ii, const uint16_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void sI16(const int ii, const uint16_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -817,7 +817,7 @@ public: /** * Store an integer without advancing the index */ - ZT_INLINE void sI32(const int ii, const uint32_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void sI32(const int ii, const uint32_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -833,7 +833,7 @@ public: /** * Store an integer without advancing the index */ - ZT_INLINE void sI64(const int ii, const uint64_t n) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void sI64(const int ii, const uint64_t n) noexcept { const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK; #ifdef ZT_NO_UNALIGNED_ACCESS @@ -853,7 +853,7 @@ public: /** * @return Capacity of this buffer (usable size of data.bytes) */ - static constexpr unsigned int capacity() noexcept + ZT_MAYBE_UNUSED static constexpr unsigned int capacity() noexcept { return ZT_BUF_MEM_SIZE; } private: diff --git a/core/CAPI.cpp b/core/CAPI.cpp index 65b132d18..0bd8e4dcc 100644 --- a/core/CAPI.cpp +++ b/core/CAPI.cpp @@ -19,6 +19,7 @@ #include "InetAddress.hpp" #include "VL1.hpp" #include "VL2.hpp" +#include "CallContext.hpp" extern "C" { @@ -30,7 +31,7 @@ extern "C" { #define ZT_PTRTOBUF(p) ((ZeroTier::Buf *)( ((uintptr_t)(p)) - ((uintptr_t)&(((ZeroTier::Buf *)0)->unsafeData[0])) )) #define ZT_BUFTOPTR(b) ((void *)(&((b)->unsafeData[0]))) -void *ZT_getBuffer() +ZT_MAYBE_UNUSED void *ZT_getBuffer() { // When external code requests a Buf, grab one from the pool (or freshly allocated) // and return it with its reference count left at zero. It's the responsibility of @@ -44,7 +45,7 @@ void *ZT_getBuffer() } } -void ZT_freeBuffer(void *b) +ZT_MAYBE_UNUSED void ZT_freeBuffer(void *b) { if (b) delete ZT_PTRTOBUF(b); @@ -55,13 +56,13 @@ struct p_queryResultBase void (*freeFunction)(const void *); }; -void ZT_freeQueryResult(const void *qr) +ZT_MAYBE_UNUSED void ZT_freeQueryResult(const void *qr) { if ((qr) && (reinterpret_cast(qr)->freeFunction)) reinterpret_cast(qr)->freeFunction(qr); } -void ZT_version(int *major, int *minor, int *revision, int *build) +ZT_MAYBE_UNUSED void ZT_version(int *major, int *minor, int *revision, int *build) { if (major) *major = ZEROTIER_VERSION_MAJOR; @@ -75,11 +76,18 @@ void ZT_version(int *major, int *minor, int *revision, int *build) /********************************************************************************************************************/ -enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const struct ZT_Node_Callbacks *callbacks, int64_t now) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_new( + ZT_Node **node, + int64_t clock, + int64_t ticks, + void *tptr, + void *uptr, + const struct ZT_Node_Callbacks *callbacks) { *node = nullptr; try { - *node = reinterpret_cast(new ZeroTier::Node(uptr, tptr, callbacks, now)); + ZeroTier::CallContext cc(clock, ticks, tptr); + *node = reinterpret_cast(new ZeroTier::Node(uptr, callbacks, cc)); return ZT_RESULT_OK; } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; @@ -90,18 +98,24 @@ enum ZT_ResultCode ZT_Node_new(ZT_Node **node, void *uptr, void *tptr, const str } } -void ZT_Node_delete(ZT_Node *node, void *tPtr) +ZT_MAYBE_UNUSED void ZT_Node_delete( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr) { try { - reinterpret_cast(node)->shutdown(tPtr); + ZeroTier::CallContext cc(clock, ticks, tptr); + reinterpret_cast(node)->shutdown(cc); delete (reinterpret_cast(node)); } catch (...) {} } -enum ZT_ResultCode ZT_Node_processWirePacket( +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, int64_t localSocket, const ZT_InetAddress *remoteAddress, const void *packetData, @@ -110,8 +124,9 @@ enum ZT_ResultCode ZT_Node_processWirePacket( volatile int64_t *nextBackgroundTaskDeadline) { try { + ZeroTier::CallContext cc(clock, ticks, tptr); ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(packetData) : new ZeroTier::Buf(packetData, packetLength & ZT_BUF_MEM_MASK)); - reinterpret_cast(node)->RR->vl1->onRemotePacket(tptr, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength); + reinterpret_cast(node)->RR->vl1->onRemotePacket(cc, localSocket, *ZeroTier::asInetAddress(remoteAddress), buf, packetLength); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -121,10 +136,11 @@ enum ZT_ResultCode ZT_Node_processWirePacket( return ZT_RESULT_OK; } -enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -136,10 +152,11 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( volatile int64_t *nextBackgroundTaskDeadline) { try { + ZeroTier::CallContext cc(clock, ticks, tptr); ZeroTier::SharedPtr< ZeroTier::Network > network(reinterpret_cast(node)->RR->networks->get(nwid)); if (likely(network)) { ZeroTier::SharedPtr< ZeroTier::Buf > buf((isZtBuffer) ? ZT_PTRTOBUF(frameData) : new ZeroTier::Buf(frameData, frameLength & ZT_BUF_MEM_MASK)); - reinterpret_cast(node)->RR->vl2->onLocalEthernet(tptr, network, ZeroTier::MAC(sourceMac), ZeroTier::MAC(destMac), etherType, vlanId, buf, frameLength); + reinterpret_cast(node)->RR->vl2->onLocalEthernet(cc, network, ZeroTier::MAC(sourceMac), ZeroTier::MAC(destMac), etherType, vlanId, buf, frameLength); return ZT_RESULT_OK; } else { return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; @@ -151,10 +168,16 @@ enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( } } -enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_processBackgroundTasks( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + volatile int64_t *nextBackgroundTaskDeadline) { try { - return reinterpret_cast(node)->processBackgroundTasks(tptr, now, nextBackgroundTaskDeadline); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->processBackgroundTasks(cc, nextBackgroundTaskDeadline); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -162,10 +185,18 @@ enum ZT_ResultCode ZT_Node_processBackgroundTasks(ZT_Node *node, void *tptr, int } } -enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, void *tptr) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_join( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + void *uptr, + uint64_t nwid, + const ZT_Fingerprint *controllerFingerprint) { try { - return reinterpret_cast(node)->join(nwid, controllerFingerprint, uptr, tptr); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->join(nwid, controllerFingerprint, uptr, cc); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -173,10 +204,17 @@ enum ZT_ResultCode ZT_Node_join(ZT_Node *node, uint64_t nwid, const ZT_Fingerpri } } -enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void *tptr) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_leave( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + void **uptr, + uint64_t nwid) { try { - return reinterpret_cast(node)->leave(nwid, uptr, tptr); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->leave(nwid, uptr, cc); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -184,10 +222,18 @@ enum ZT_ResultCode ZT_Node_leave(ZT_Node *node, uint64_t nwid, void **uptr, void } } -enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastSubscribe( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + uint64_t nwid, + uint64_t multicastGroup, + unsigned long multicastAdi) { try { - return reinterpret_cast(node)->multicastSubscribe(tptr, nwid, multicastGroup, multicastAdi); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->multicastSubscribe(cc, nwid, multicastGroup, multicastAdi); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -195,10 +241,18 @@ enum ZT_ResultCode ZT_Node_multicastSubscribe(ZT_Node *node, void *tptr, uint64_ } } -enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_multicastUnsubscribe( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + uint64_t nwid, + uint64_t multicastGroup, + unsigned long multicastAdi) { try { - return reinterpret_cast(node)->multicastUnsubscribe(nwid, multicastGroup, multicastAdi); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->multicastUnsubscribe(cc, nwid, multicastGroup, multicastAdi); } catch (std::bad_alloc &exc) { return ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY; } catch (...) { @@ -206,29 +260,44 @@ enum ZT_ResultCode ZT_Node_multicastUnsubscribe(ZT_Node *node, uint64_t nwid, ui } } -uint64_t ZT_Node_address(ZT_Node *node) +ZT_MAYBE_UNUSED uint64_t ZT_Node_address(ZT_Node *node) { return reinterpret_cast(node)->RR->identity.address().toInt(); } -const ZT_Identity *ZT_Node_identity(ZT_Node *node) +ZT_MAYBE_UNUSED const ZT_Identity *ZT_Node_identity(ZT_Node *node) { return (const ZT_Identity *)(&(reinterpret_cast(node)->identity())); } -void ZT_Node_status(ZT_Node *node, ZT_NodeStatus *status) +ZT_MAYBE_UNUSED void ZT_Node_status( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + ZT_NodeStatus *status) { try { reinterpret_cast(node)->status(status); } catch (...) {} } -ZT_PeerList *ZT_Node_peers(ZT_Node *node) +ZT_MAYBE_UNUSED ZT_PeerList *ZT_Node_peers( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr) { try { - return reinterpret_cast(node)->peers(); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->peers(cc); } catch (...) { return (ZT_PeerList *)0; } } -ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid) +ZT_MAYBE_UNUSED ZT_VirtualNetworkConfig *ZT_Node_networkConfig( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + uint64_t nwid) { try { return reinterpret_cast(node)->networkConfig(nwid); @@ -237,7 +306,7 @@ ZT_VirtualNetworkConfig *ZT_Node_networkConfig(ZT_Node *node, uint64_t nwid) } } -ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) +ZT_MAYBE_UNUSED ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) { try { return reinterpret_cast(node)->networks(); @@ -246,49 +315,67 @@ ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node) } } -int ZT_Node_tryPeer( +ZT_MAYBE_UNUSED void ZT_Node_setNetworkUserPtr( ZT_Node *node, - void *tptr, - const ZT_Fingerprint *fp, - const ZT_Endpoint *endpoint, - int retries) + uint64_t nwid, + void *ptr) { try { - return reinterpret_cast(node)->tryPeer(tptr, fp, endpoint, retries); - } catch (...) { - return 0; - } + reinterpret_cast(node)->setNetworkUserPtr(nwid, ptr); + } catch (...) {} } -enum ZT_CertificateError ZT_Node_addCertificate( +ZT_MAYBE_UNUSED void ZT_Node_setInterfaceAddresses( ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, + const ZT_InterfaceAddress *addrs, + unsigned int addrCount) +{ + try { + reinterpret_cast(node)->setInterfaceAddresses(addrs, addrCount); + } catch (...) {} +} + +ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Node_addCertificate( + ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, unsigned int localTrust, const ZT_Certificate *cert, const void *certData, unsigned int certSize) { try { - return reinterpret_cast(node)->addCertificate(tptr, now, localTrust, cert, certData, certSize); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->addCertificate(cc, localTrust, cert, certData, certSize); } catch (...) { return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; } } -ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( +ZT_MAYBE_UNUSED enum ZT_ResultCode ZT_Node_deleteCertificate( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, const void *serialNo) { try { - return reinterpret_cast(node)->deleteCertificate(tptr, serialNo); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->deleteCertificate(cc, serialNo); } catch (...) { return ZT_RESULT_ERROR_INTERNAL; } } -ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) +ZT_MAYBE_UNUSED ZT_CertificateList *ZT_Node_listCertificates( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr) { try { return reinterpret_cast(node)->listCertificates(); @@ -297,42 +384,27 @@ ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node) } } -void ZT_Node_setNetworkUserPtr(ZT_Node *node, uint64_t nwid, void *ptr) -{ - try { - reinterpret_cast(node)->setNetworkUserPtr(nwid, ptr); - } catch (...) {} -} - -void ZT_Node_setInterfaceAddresses(ZT_Node *node, const ZT_InterfaceAddress *addrs, unsigned int addrCount) -{ - try { - reinterpret_cast(node)->setInterfaceAddresses(addrs, addrCount); - } catch (...) {} -} - -enum ZT_ResultCode ZT_Node_addPeer( +ZT_MAYBE_UNUSED int ZT_Node_sendUserMessage( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - const ZT_Identity *id) + uint64_t dest, + uint64_t typeId, + const void *data, + unsigned int len) { try { - return reinterpret_cast(node)->addPeer(tptr, id); - } catch (...) { - return ZT_RESULT_ERROR_INTERNAL; - } -} - -int ZT_Node_sendUserMessage(ZT_Node *node, void *tptr, uint64_t dest, uint64_t typeId, const void *data, unsigned int len) -{ - try { - return reinterpret_cast(node)->sendUserMessage(tptr, dest, typeId, data, len); + ZeroTier::CallContext cc(clock, ticks, tptr); + return reinterpret_cast(node)->sendUserMessage(cc, dest, typeId, data, len); } catch (...) { return 0; } } -void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance) +ZT_MAYBE_UNUSED void ZT_Node_setController( + ZT_Node *node, + void *networkControllerInstance) { try { reinterpret_cast(node)->setController(networkControllerInstance); @@ -341,20 +413,20 @@ void ZT_Node_setController(ZT_Node *node, void *networkControllerInstance) /********************************************************************************************************************/ -ZT_Locator *ZT_Locator_create( - int64_t ts, +ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_create( + int64_t rev, const ZT_Endpoint *endpoints, - const ZT_EndpointAttributes *endpointAttributes, // TODO: not used yet + const ZT_EndpointAttributes *endpointAttributes, unsigned int endpointCount, const ZT_Identity *signer) { try { - if ((ts <= 0) || (!endpoints) || (endpointCount == 0) || (!signer)) + if ((!endpoints) || (endpointCount == 0) || (!signer)) return nullptr; ZeroTier::Locator *loc = new ZeroTier::Locator(); for (unsigned int i = 0;i < endpointCount;++i) loc->add(reinterpret_cast< const ZeroTier::Endpoint * >(endpoints)[i], ZeroTier::Locator::EndpointAttributes::DEFAULT); - if (!loc->sign(ts, *reinterpret_cast< const ZeroTier::Identity * >(signer))) { + if (!loc->sign(rev, *reinterpret_cast< const ZeroTier::Identity * >(signer))) { delete loc; return nullptr; } @@ -364,7 +436,7 @@ ZT_Locator *ZT_Locator_create( } } -ZT_Locator *ZT_Locator_fromString(const char *str) +ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_fromString(const char *str) { try { if (!str) @@ -380,7 +452,7 @@ ZT_Locator *ZT_Locator_fromString(const char *str) } } -ZT_Locator *ZT_Locator_unmarshal( +ZT_MAYBE_UNUSED ZT_Locator *ZT_Locator_unmarshal( const void *data, unsigned int len) { @@ -398,14 +470,14 @@ ZT_Locator *ZT_Locator_unmarshal( } } -int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize) +ZT_MAYBE_UNUSED int ZT_Locator_marshal(const ZT_Locator *loc, void *buf, unsigned int bufSize) { if ((!loc) || (bufSize < ZT_LOCATOR_MARSHAL_SIZE_MAX)) return -1; return reinterpret_cast(loc)->marshal(reinterpret_cast(buf), false); } -char *ZT_Locator_toString( +ZT_MAYBE_UNUSED char *ZT_Locator_toString( const ZT_Locator *loc, char *buf, int capacity) @@ -415,26 +487,24 @@ char *ZT_Locator_toString( return reinterpret_cast(loc)->toString(buf); } -const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc) +ZT_MAYBE_UNUSED const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc) { if (!loc) return nullptr; return (ZT_Fingerprint *) (&(reinterpret_cast(loc)->signer())); } -int64_t ZT_Locator_timestamp(const ZT_Locator *loc) +ZT_MAYBE_UNUSED int64_t ZT_Locator_revision(const ZT_Locator *loc) { if (!loc) return 0; - return reinterpret_cast(loc)->timestamp(); + return reinterpret_cast(loc)->revision(); } -unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc) -{ - return (loc) ? (unsigned int) (reinterpret_cast(loc)->endpoints().size()) : 0; -} +ZT_MAYBE_UNUSED unsigned int ZT_Locator_endpointCount(const ZT_Locator *loc) +{ return (loc) ? (unsigned int) (reinterpret_cast(loc)->endpoints().size()) : 0; } -const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep) +ZT_MAYBE_UNUSED const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int ep) { if (!loc) return nullptr; @@ -443,14 +513,14 @@ const ZT_Endpoint *ZT_Locator_endpoint(const ZT_Locator *loc, const unsigned int return reinterpret_cast(&(reinterpret_cast(loc)->endpoints()[ep])); } -int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer) +ZT_MAYBE_UNUSED int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer) { if ((!loc) || (!signer)) return 0; return reinterpret_cast(loc)->verify(*reinterpret_cast(signer)) ? 1 : 0; } -void ZT_Locator_delete(const ZT_Locator *loc) +ZT_MAYBE_UNUSED void ZT_Locator_delete(const ZT_Locator *loc) { if (loc) delete reinterpret_cast(loc); @@ -458,7 +528,7 @@ void ZT_Locator_delete(const ZT_Locator *loc) /********************************************************************************************************************/ -ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) +ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) { if ((type != ZT_IDENTITY_TYPE_C25519) && (type != ZT_IDENTITY_TYPE_P384)) return nullptr; @@ -471,7 +541,7 @@ ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type) } } -ZT_Identity *ZT_Identity_clone(const ZT_Identity *id) +ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_clone(const ZT_Identity *id) { if (id) { try { @@ -483,7 +553,7 @@ ZT_Identity *ZT_Identity_clone(const ZT_Identity *id) return nullptr; } -ZT_Identity *ZT_Identity_fromString(const char *idStr) +ZT_MAYBE_UNUSED ZT_Identity *ZT_Identity_fromString(const char *idStr) { if (!idStr) return nullptr; @@ -499,14 +569,14 @@ ZT_Identity *ZT_Identity_fromString(const char *idStr) } } -int ZT_Identity_validate(const ZT_Identity *id) +ZT_MAYBE_UNUSED int ZT_Identity_validate(const ZT_Identity *id) { if (!id) return 0; return reinterpret_cast(id)->locallyValidate() ? 1 : 0; } -unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength) +ZT_MAYBE_UNUSED unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned int len, void *signature, unsigned int signatureBufferLength) { if (!id) return 0; @@ -515,21 +585,21 @@ unsigned int ZT_Identity_sign(const ZT_Identity *id, const void *data, unsigned return reinterpret_cast(id)->sign(data, len, signature, signatureBufferLength); } -int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen) +ZT_MAYBE_UNUSED int ZT_Identity_verify(const ZT_Identity *id, const void *data, unsigned int len, const void *signature, unsigned int sigLen) { if ((!id) || (!signature) || (!sigLen)) return 0; return reinterpret_cast(id)->verify(data, len, signature, sigLen) ? 1 : 0; } -enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id) +ZT_MAYBE_UNUSED enum ZT_IdentityType ZT_Identity_type(const ZT_Identity *id) { if (!id) return (ZT_IdentityType)0; return (enum ZT_IdentityType)reinterpret_cast(id)->type(); } -char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate) +ZT_MAYBE_UNUSED char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int includePrivate) { if ((!id) || (!buf) || (capacity < ZT_IDENTITY_STRING_BUFFER_LENGTH)) return nullptr; @@ -537,28 +607,28 @@ char *ZT_Identity_toString(const ZT_Identity *id, char *buf, int capacity, int i return buf; } -int ZT_Identity_hasPrivate(const ZT_Identity *id) +ZT_MAYBE_UNUSED int ZT_Identity_hasPrivate(const ZT_Identity *id) { if (!id) return 0; return reinterpret_cast(id)->hasPrivate() ? 1 : 0; } -uint64_t ZT_Identity_address(const ZT_Identity *id) +ZT_MAYBE_UNUSED uint64_t ZT_Identity_address(const ZT_Identity *id) { if (!id) return 0; return reinterpret_cast(id)->address(); } -const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) +ZT_MAYBE_UNUSED const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id) { if (!id) return nullptr; return &(reinterpret_cast(id)->fingerprint()); } -int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b) +ZT_MAYBE_UNUSED int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b) { if (a) { if (b) { @@ -579,7 +649,7 @@ int ZT_Identity_compare(const ZT_Identity *a, const ZT_Identity *b) } } -void ZT_Identity_delete(const ZT_Identity *id) +ZT_MAYBE_UNUSED void ZT_Identity_delete(const ZT_Identity *id) { if (id) delete reinterpret_cast(id); @@ -587,7 +657,7 @@ void ZT_Identity_delete(const ZT_Identity *id) /********************************************************************************************************************/ -int ZT_Certificate_newSubjectUniqueId( +ZT_MAYBE_UNUSED int ZT_Certificate_newSubjectUniqueId( enum ZT_CertificateUniqueIdType type, void *uniqueId, int *uniqueIdSize, @@ -610,7 +680,7 @@ int ZT_Certificate_newSubjectUniqueId( } } -int ZT_Certificate_newCSR( +ZT_MAYBE_UNUSED int ZT_Certificate_newCSR( const ZT_Certificate_Subject *subject, const void *uniqueId, int uniqueIdSize, @@ -633,7 +703,7 @@ int ZT_Certificate_newCSR( } } -int ZT_Certificate_sign( +ZT_MAYBE_UNUSED int ZT_Certificate_sign( const ZT_Certificate *cert, const ZT_Identity *signer, void *signedCert, @@ -658,7 +728,7 @@ int ZT_Certificate_sign( } } -enum ZT_CertificateError ZT_Certificate_decode( +ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_decode( const ZT_Certificate **decodedCert, const void *cert, int certSize, @@ -687,7 +757,7 @@ enum ZT_CertificateError ZT_Certificate_decode( } } -int ZT_Certificate_encode( +ZT_MAYBE_UNUSED int ZT_Certificate_encode( const ZT_Certificate *cert, void *encoded, int *encodedSize) @@ -707,7 +777,7 @@ int ZT_Certificate_encode( } } -enum ZT_CertificateError ZT_Certificate_verify( +ZT_MAYBE_UNUSED enum ZT_CertificateError ZT_Certificate_verify( const ZT_Certificate *cert, int64_t clock) { @@ -720,7 +790,7 @@ enum ZT_CertificateError ZT_Certificate_verify( } } -const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) +ZT_MAYBE_UNUSED const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) { try { if (!cert) @@ -731,7 +801,7 @@ const ZT_Certificate *ZT_Certificate_clone(const ZT_Certificate *cert) } } -void ZT_Certificate_delete(const ZT_Certificate *cert) +ZT_MAYBE_UNUSED void ZT_Certificate_delete(const ZT_Certificate *cert) { try { if (cert) @@ -741,7 +811,7 @@ void ZT_Certificate_delete(const ZT_Certificate *cert) /********************************************************************************************************************/ -char *ZT_Endpoint_toString( +ZT_MAYBE_UNUSED char *ZT_Endpoint_toString( const ZT_Endpoint *ep, char *buf, int capacity) @@ -751,7 +821,7 @@ char *ZT_Endpoint_toString( return reinterpret_cast(ep)->toString(buf); } -int ZT_Endpoint_fromString( +ZT_MAYBE_UNUSED int ZT_Endpoint_fromString( ZT_Endpoint *ep, const char *str) { @@ -760,7 +830,7 @@ int ZT_Endpoint_fromString( return reinterpret_cast(ep)->fromString(str) ? ZT_RESULT_OK : ZT_RESULT_ERROR_BAD_PARAMETER; } -int ZT_Endpoint_fromBytes( +ZT_MAYBE_UNUSED int ZT_Endpoint_fromBytes( ZT_Endpoint *ep, const void *bytes, unsigned int len) @@ -772,14 +842,14 @@ int ZT_Endpoint_fromBytes( /********************************************************************************************************************/ -char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity) +ZT_MAYBE_UNUSED char *ZT_Fingerprint_toString(const ZT_Fingerprint *fp, char *buf, int capacity) { if (capacity < ZT_FINGERPRINT_STRING_SIZE_MAX) return nullptr; return reinterpret_cast(fp)->toString(buf); } -int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s) +ZT_MAYBE_UNUSED int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s) { if ((!fp)||(!s)) return 0; @@ -793,13 +863,13 @@ int ZT_Fingerprint_fromString(ZT_Fingerprint *fp, const char *s) /********************************************************************************************************************/ -void ZT_InetAddress_clear(ZT_InetAddress *ia) +ZT_MAYBE_UNUSED void ZT_InetAddress_clear(ZT_InetAddress *ia) { if (likely(ia != nullptr)) ZeroTier::Utils::zero(ia); } -char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap) +ZT_MAYBE_UNUSED char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int cap) { if (likely((cap > 0)&&(buf != nullptr))) { if (likely((ia != nullptr)&&(cap >= ZT_INETADDRESS_STRING_SIZE_MAX))) { @@ -811,7 +881,7 @@ char *ZT_InetAddress_toString(const ZT_InetAddress *ia, char *buf, unsigned int return buf; } -int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str) +ZT_MAYBE_UNUSED int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str) { if (likely((ia != nullptr)&&(str != nullptr))) { return (int)reinterpret_cast(ia)->fromString(str); @@ -819,53 +889,53 @@ int ZT_InetAddress_fromString(ZT_InetAddress *ia, const char *str) return 0; } -void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr) +ZT_MAYBE_UNUSED void ZT_InetAddress_set(ZT_InetAddress *ia, const void *saddr) { if (likely(ia != nullptr)) (*reinterpret_cast(ia)) = reinterpret_cast(saddr); } -void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port) +ZT_MAYBE_UNUSED void ZT_InetAddress_setIpBytes(ZT_InetAddress *ia, const void *ipBytes, unsigned int ipLen, unsigned int port) { if (likely(ia != nullptr)) reinterpret_cast(ia)->set(ipBytes, ipLen, port); } -void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port) +ZT_MAYBE_UNUSED void ZT_InetAddress_setPort(ZT_InetAddress *ia, unsigned int port) { if (likely(ia != nullptr)) reinterpret_cast(ia)->setPort(port); } -unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia) +ZT_MAYBE_UNUSED unsigned int ZT_InetAddress_port(const ZT_InetAddress *ia) { if (likely(ia != nullptr)) return reinterpret_cast(ia)->port(); return 0; } -int ZT_InetAddress_isNil(const ZT_InetAddress *ia) +ZT_MAYBE_UNUSED int ZT_InetAddress_isNil(const ZT_InetAddress *ia) { if (!ia) return 0; return (int)((bool)(*reinterpret_cast(ia))); } -int ZT_InetAddress_isV4(const ZT_InetAddress *ia) +ZT_MAYBE_UNUSED int ZT_InetAddress_isV4(const ZT_InetAddress *ia) { if (!ia) return 0; return (int)(reinterpret_cast(ia))->isV4(); } -int ZT_InetAddress_isV6(const ZT_InetAddress *ia) +ZT_MAYBE_UNUSED int ZT_InetAddress_isV6(const ZT_InetAddress *ia) { if (!ia) return 0; return (int)(reinterpret_cast(ia))->isV6(); } -unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf) +ZT_MAYBE_UNUSED unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf) { if (ia) { switch(reinterpret_cast(ia)->as.sa.sa_family) { @@ -880,14 +950,14 @@ unsigned int ZT_InetAddress_ipBytes(const ZT_InetAddress *ia, void *buf) return 0; } -enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia) +ZT_MAYBE_UNUSED enum ZT_InetAddress_IpScope ZT_InetAddress_ipScope(const ZT_InetAddress *ia) { if (likely(ia != nullptr)) return reinterpret_cast(ia)->ipScope(); return ZT_IP_SCOPE_NONE; } -int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b) +ZT_MAYBE_UNUSED int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b) { if (a) { if (b) { @@ -910,7 +980,7 @@ int ZT_InetAddress_compare(const ZT_InetAddress *a, const ZT_InetAddress *b) /********************************************************************************************************************/ -int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *const arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int)) +ZT_MAYBE_UNUSED int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *const arg, void (*f)(void *, const char *, unsigned int, const void *, unsigned int)) { ZeroTier::Dictionary d; if (d.decode(dict, len)) { @@ -924,7 +994,7 @@ int ZT_Dictionary_parse(const void *const dict, const unsigned int len, void *co /********************************************************************************************************************/ -uint64_t ZT_random() +ZT_MAYBE_UNUSED uint64_t ZT_random() { return ZeroTier::Utils::random(); } } // extern "C" diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index ec68bc8f1..27dd2dfac 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -11,6 +11,7 @@ set(core_headers Address.hpp Buf.hpp C25519.hpp + CallContext.hpp CapabilityCredential.hpp Certificate.hpp Defaults.hpp diff --git a/core/CallContext.hpp b/core/CallContext.hpp new file mode 100644 index 000000000..4ef9d8143 --- /dev/null +++ b/core/CallContext.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c)2013-2021 ZeroTier, Inc. + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file in the project's root directory. + * + * Change Date: 2026-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2.0 of the Apache License. + */ +/****/ + +#ifndef ZT_CALLCONTEXT_HPP +#define ZT_CALLCONTEXT_HPP + +#include "Constants.hpp" + +namespace ZeroTier { + +/** + * A per-API-call equivalent to the runtime + * + * This captures several things that are passed into API calls and follow + * the call chain. Some such as tPtr may be supplied to callbacks. + */ +class CallContext +{ +public: + ZT_INLINE CallContext(const int64_t c, const int64_t t, void *const p) : + clock(c), + ticks(t), + tPtr(p) + {} + + /** + * Real world time in milliseconds since Unix epoch or -1 if unknown. + * + * This is used for things like checking certificate expiration. If it's + * not known then the value may be inferred from peers/roots or some + * features may be disabled. + */ + const int64_t clock; + + /** + * Monotonic process or system clock in milliseconds since an arbitrary point. + * + * This is never -1 or undefined and is used for most timings. + */ + const int64_t ticks; + + /** + * An arbitrary pointer users pass into calls that follows the call chain + * + * By passing this back to callbacks state can be kept by the caller using + * a mechanism that is faster (on most platforms) than thread-local storage. + */ + void *const tPtr; +}; + +} // namespace ZeroTier + +#endif diff --git a/core/CapabilityCredential.cpp b/core/CapabilityCredential.cpp index ffcdd59fb..bf1c61be3 100644 --- a/core/CapabilityCredential.cpp +++ b/core/CapabilityCredential.cpp @@ -38,7 +38,7 @@ int CapabilityCredential::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], Utils::storeBigEndian(data + p, m_nwid); p += 8; - Utils::storeBigEndian(data + p, (uint64_t) m_ts); + Utils::storeBigEndian(data + p, (uint64_t) m_timestamp); p += 8; Utils::storeBigEndian(data + p, m_id); p += 4; @@ -84,7 +84,7 @@ int CapabilityCredential::unmarshal(const uint8_t *data, int len) noexcept return -1; m_nwid = Utils::loadBigEndian(data); - m_ts = (int64_t) Utils::loadBigEndian(data + 8); + m_timestamp = (int64_t) Utils::loadBigEndian(data + 8); m_id = Utils::loadBigEndian(data + 16); const unsigned int rc = Utils::loadBigEndian(data + 20); diff --git a/core/CapabilityCredential.hpp b/core/CapabilityCredential.hpp index 923ff3113..0707f8abb 100644 --- a/core/CapabilityCredential.hpp +++ b/core/CapabilityCredential.hpp @@ -51,21 +51,23 @@ class CapabilityCredential : public Credential friend class Credential; public: - static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_CAPABILITY; } + static constexpr ZT_CredentialType credentialType() noexcept + { return ZT_CREDENTIAL_TYPE_CAPABILITY; } - ZT_INLINE CapabilityCredential() noexcept { memoryZero(this); } + ZT_INLINE CapabilityCredential() noexcept + { memoryZero(this); } /** * @param id Capability ID * @param nwid Network ID - * @param ts Timestamp (at controller) + * @param timestamp Timestamp (at controller) * @param mccl Maximum custody chain length (1 to create non-transferable capability) * @param rules Network flow rules for this capability * @param ruleCount Number of flow rules */ - ZT_INLINE CapabilityCredential(const uint32_t id, const uint64_t nwid, const int64_t ts, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) + ZT_INLINE CapabilityCredential(const uint32_t id, const uint64_t nwid, const int64_t timestamp, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) m_nwid(nwid), - m_ts(ts), + m_timestamp(timestamp), m_id(id), m_ruleCount((ruleCount < ZT_MAX_CAPABILITY_RULES) ? ruleCount : ZT_MAX_CAPABILITY_RULES), m_signatureLength(0) @@ -77,20 +79,38 @@ public: /** * @return Rules -- see ruleCount() for size of array */ - ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept { return m_rules; } + ZT_INLINE const ZT_VirtualNetworkRule *rules() const noexcept + { return m_rules; } /** * @return Number of rules in rules() */ - ZT_INLINE unsigned int ruleCount() const noexcept { return m_ruleCount; } + ZT_INLINE unsigned int ruleCount() const noexcept + { return m_ruleCount; } - ZT_INLINE uint32_t id() const noexcept { return m_id; } - ZT_INLINE uint64_t networkId() const noexcept { return m_nwid; } - ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } - ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } - ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } - ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } + ZT_INLINE uint32_t id() const noexcept + { return m_id; } + + ZT_INLINE uint64_t networkId() const noexcept + { return m_nwid; } + + ZT_INLINE int64_t timestamp() const noexcept + { return m_timestamp; } + + ZT_INLINE int64_t revision() const noexcept + { return m_timestamp; } + + ZT_INLINE const Address &issuedTo() const noexcept + { return m_issuedTo; } + + ZT_INLINE const Address &signer() const noexcept + { return m_signedBy; } + + ZT_INLINE const uint8_t *signature() const noexcept + { return m_signature; } + + ZT_INLINE unsigned int signatureLength() const noexcept + { return m_signatureLength; } /** * Sign this capability and add signature to its chain of custody @@ -105,18 +125,22 @@ public: * @param to Recipient of this signature * @return True if signature successful and chain of custody appended */ - bool sign(const Identity &from,const Address &to) noexcept; + bool sign(const Identity &from, const Address &to) noexcept; /** * Verify this capability's chain of custody and signatures * * @param RR Runtime environment to provide for peer lookup, etc. */ - ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const noexcept { return s_verify(RR, tPtr, *this); } + ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept + { return s_verify(RR, cc, *this); } - static constexpr int marshalSizeMax() noexcept { return ZT_CAPABILITY_MARSHAL_SIZE_MAX; } - int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],bool forSign = false) const noexcept; - int unmarshal(const uint8_t *data,int len) noexcept; + static constexpr int marshalSizeMax() noexcept + { return ZT_CAPABILITY_MARSHAL_SIZE_MAX; } + + int marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept; + + int unmarshal(const uint8_t *data, int len) noexcept; /** * Marshal a set of virtual network rules @@ -126,7 +150,7 @@ public: * @param ruleCount Number of rules * @return Number of bytes written or -1 on error */ - static int marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetworkRule *rules,unsigned int ruleCount) noexcept; + static int marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *rules, unsigned int ruleCount) noexcept; /** * Unmarshal a set of virtual network rules @@ -138,17 +162,21 @@ public: * @param maxRuleCount Capacity of rules buffer * @return Number of bytes unmarshaled or -1 on error */ - static int unmarshalVirtualNetworkRules(const uint8_t *data,int len,ZT_VirtualNetworkRule *rules,unsigned int &ruleCount,unsigned int maxRuleCount) noexcept; + static int unmarshalVirtualNetworkRules(const uint8_t *data, int len, ZT_VirtualNetworkRule *rules, unsigned int &ruleCount, unsigned int maxRuleCount) noexcept; // Provides natural sort order by ID - ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept { return (m_id < c.m_id); } + ZT_INLINE bool operator<(const CapabilityCredential &c) const noexcept + { return (m_id < c.m_id); } - ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); } - ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept { return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); } + ZT_INLINE bool operator==(const CapabilityCredential &c) const noexcept + { return (memcmp(this, &c, sizeof(CapabilityCredential)) == 0); } + + ZT_INLINE bool operator!=(const CapabilityCredential &c) const noexcept + { return (memcmp(this, &c, sizeof(CapabilityCredential)) != 0); } private: uint64_t m_nwid; - int64_t m_ts; + int64_t m_timestamp; uint32_t m_id; unsigned int m_ruleCount; ZT_VirtualNetworkRule m_rules[ZT_MAX_CAPABILITY_RULES]; diff --git a/core/Certificate.cpp b/core/Certificate.cpp index b3011413d..5bacc980d 100644 --- a/core/Certificate.cpp +++ b/core/Certificate.cpp @@ -167,7 +167,7 @@ void Certificate::addSubjectCertificate(const uint8_t serialNo[ZT_SHA384_DIGEST_ // Enlarge array of uint8_t pointers, set new pointer to local copy of serial, and set // certificates to point to potentially reallocated array. - m_subjectCertificates.push_back(m_serials.front().bytes()); + m_subjectCertificates.push_back(reinterpret_cast(m_serials.front().data)); this->subject.certificates = m_subjectCertificates.data(); this->subject.certificateCount = (unsigned int)m_subjectCertificates.size(); } @@ -187,6 +187,7 @@ void Certificate::addSubjectUpdateUrl(const char *url) this->subject.updateURLCount = (unsigned int)m_updateUrls.size(); } +/* void Certificate::setExtendedAttributes(const Dictionary &x) { m_extendedAttributes.clear(); @@ -194,6 +195,7 @@ void Certificate::setExtendedAttributes(const Dictionary &x) this->extendedAttributes = m_extendedAttributes.data(); this->extendedAttributesSize = (unsigned int)m_extendedAttributes.size(); } +*/ bool Certificate::setSubjectUniqueId(const uint8_t uniqueId[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE], const uint8_t uniqueIdPrivate[ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_PRIVATE_SIZE]) { diff --git a/core/Certificate.hpp b/core/Certificate.hpp index 9e722961c..f78274286 100644 --- a/core/Certificate.hpp +++ b/core/Certificate.hpp @@ -110,7 +110,7 @@ public: * * @param x Extended attributes (set by issuer) */ - void setExtendedAttributes(const Dictionary &x); + //void setExtendedAttributes(const Dictionary &x); /** * Set the unique ID of this certificate's subject diff --git a/core/Constants.hpp b/core/Constants.hpp index 324dd7dea..f351cf081 100644 --- a/core/Constants.hpp +++ b/core/Constants.hpp @@ -102,9 +102,9 @@ #define ZT_NETWORK_HOUSEKEEPING_PERIOD 30000 /** - * How often to rank roots + * Period between calls to update() in TrustStore */ -#define ZT_ROOT_RANK_PERIOD 5000 +#define ZT_TRUSTSTORE_UPDATE_PERIOD 300000 /** * Delay between WHOIS retries in ms diff --git a/core/Containers.hpp b/core/Containers.hpp index 5b10e1282..b70d58eba 100644 --- a/core/Containers.hpp +++ b/core/Containers.hpp @@ -27,9 +27,11 @@ #include #ifdef __CPP11__ + #include #include #include + #endif namespace ZeroTier { @@ -43,14 +45,15 @@ public: {} template< typename I > - ZT_INLINE Vector(I begin,I end) : + ZT_INLINE Vector(I begin, I end) : std::vector< V >(begin, end) {} }; template< typename V > class List : public std::list< V > -{}; +{ +}; #ifdef __CPP11__ @@ -78,11 +81,13 @@ struct intl_MapHasher template< typename K, typename V > class Map : public std::unordered_map< K, V, intl_MapHasher > -{}; +{ +}; template< typename K, typename V > class MultiMap : public std::unordered_multimap< K, V, intl_MapHasher, std::equal_to< K > > -{}; +{ +}; #else @@ -98,13 +103,15 @@ class MultiMap : public std::multimap< K, V > template< typename K, typename V > class SortedMap : public std::map< K, V > -{}; +{ +}; #ifdef __CPP11__ template< typename V > class ForwardList : public std::forward_list< V > -{}; +{ +}; #else @@ -116,7 +123,8 @@ class ForwardList : public std::list< V > template< typename V > class Set : public std::set< V, std::less< V > > -{}; +{ +}; typedef std::string String; @@ -130,11 +138,17 @@ struct H384 ZT_INLINE H384() noexcept { Utils::zero< sizeof(data) >(data); } + ZT_INLINE H384(const H384 &b) noexcept + { Utils::copy< 48 >(data, b.data); } + explicit ZT_INLINE H384(const void *const d) noexcept { Utils::copy< 48 >(data, d); } - ZT_INLINE const uint8_t *bytes() const noexcept - { return reinterpret_cast(data); } + ZT_INLINE H384 &operator=(const H384 &b) noexcept + { + Utils::copy< 48 >(data, b.data); + return *this; + } ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)data[0]; } @@ -151,12 +165,12 @@ struct H384 ZT_INLINE bool operator<(const H384 &b) const noexcept { return std::lexicographical_compare(data, data + 6, b.data, b.data + 6); } - ZT_INLINE bool operator>(const H384 &b) const noexcept - { return (b < *this); } - ZT_INLINE bool operator<=(const H384 &b) const noexcept { return !(b < *this); } + ZT_INLINE bool operator>(const H384 &b) const noexcept + { return (b < *this); } + ZT_INLINE bool operator>=(const H384 &b) const noexcept { return !(*this < b); } }; @@ -164,7 +178,7 @@ struct H384 static_assert(sizeof(H384) == 48, "H384 contains unnecessary padding"); /** - * A byte array + * A fixed size byte array * * @tparam S Size in bytes */ @@ -172,6 +186,53 @@ template< unsigned long S > struct Blob { uint8_t data[S]; + + ZT_INLINE Blob() noexcept + { Utils::zero< S >(data); } + + ZT_INLINE Blob(const Blob &b) noexcept + { Utils::copy< S >(data, b.data); } + + explicit ZT_INLINE Blob(const void *const d) noexcept + { Utils::copy< S >(data, d); } + + explicit ZT_INLINE Blob(const void *const d, const unsigned int l) noexcept + { + Utils::copy(data, d, l); + if (l < S) { + Utils::zero(data + l, S - l); + } + } + + ZT_INLINE Blob &operator=(const Blob &b) noexcept + { + Utils::copy< S >(data, b.data); + return *this; + } + + ZT_INLINE unsigned long hashCode() const noexcept + { return Utils::fnv1a32(data, (unsigned int)S); } + + ZT_INLINE operator bool() const noexcept + { return Utils::allZero(data, (unsigned int)S); } + + ZT_INLINE bool operator==(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) == 0); } + + ZT_INLINE bool operator!=(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) != 0); } + + ZT_INLINE bool operator<(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) < 0); } + + ZT_INLINE bool operator<=(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) <= 0); } + + ZT_INLINE bool operator>(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) > 0); } + + ZT_INLINE bool operator>=(const Blob &b) const noexcept + { return (memcmp(data, b.data, S) >= 0); } }; } // ZeroTier diff --git a/core/Credential.cpp b/core/Credential.cpp index 590d0ac55..f35c8ee68 100644 --- a/core/Credential.cpp +++ b/core/Credential.cpp @@ -42,43 +42,50 @@ namespace ZeroTier { -template -static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment *RR,void *tPtr,CRED credential) +template< typename CRED > +static ZT_INLINE Credential::VerifyResult p_credVerify(const RuntimeEnvironment *RR, CallContext &cc, CRED credential) { uint8_t tmp[ZT_BUF_MEM_SIZE + 16]; const Address signedBy(credential.signer()); const uint64_t networkId = credential.networkId(); - if ((!signedBy)||(signedBy != Network::controllerFor(networkId))) + if ((!signedBy) || (signedBy != Network::controllerFor(networkId))) return Credential::VERIFY_BAD_SIGNATURE; - const SharedPtr peer(RR->topology->peer(tPtr,signedBy)); + const SharedPtr< Peer > peer(RR->topology->peer(cc, signedBy)); if (!peer) return Credential::VERIFY_NEED_IDENTITY; try { - int l = credential.marshal(tmp,true); + int l = credential.marshal(tmp, true); if (l <= 0) return Credential::VERIFY_BAD_SIGNATURE; - return (peer->identity().verify(tmp,(unsigned int)l,credential.signature(),credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE); - } catch ( ... ) {} + return (peer->identity().verify(tmp, (unsigned int)l, credential.signature(), credential.signatureLength()) ? Credential::VERIFY_OK : Credential::VERIFY_BAD_SIGNATURE); + } catch (...) {} return Credential::VERIFY_BAD_SIGNATURE; } -Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const RevocationCredential &credential) { return p_credVerify(RR, tPtr, credential); } -Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const TagCredential &credential) { return p_credVerify(RR, tPtr, credential); } -Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const CapabilityCredential &credential) { return p_credVerify(RR, tPtr, credential); } -Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const OwnershipCredential &credential) { return p_credVerify(RR, tPtr, credential); } +Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const RevocationCredential &credential) +{ return p_credVerify(RR, cc, credential); } -Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, void *tPtr, const MembershipCredential &credential) +Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const TagCredential &credential) +{ return p_credVerify(RR, cc, credential); } + +Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const CapabilityCredential &credential) +{ return p_credVerify(RR, cc, credential); } + +Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const OwnershipCredential &credential) +{ return p_credVerify(RR, cc, credential); } + +Credential::VerifyResult Credential::s_verify(const RuntimeEnvironment *RR, CallContext &cc, const MembershipCredential &credential) { // Sanity check network ID. if ((!credential.m_signedBy) || (credential.m_signedBy != Network::controllerFor(credential.m_networkId))) return Credential::VERIFY_BAD_SIGNATURE; // If we don't know the peer, get its identity. This shouldn't happen here but should be handled. - const SharedPtr peer(RR->topology->peer(tPtr,credential.m_signedBy)); + const SharedPtr< Peer > peer(RR->topology->peer(cc, credential.m_signedBy)); if (!peer) return Credential::VERIFY_NEED_IDENTITY; diff --git a/core/Credential.hpp b/core/Credential.hpp index c1f7e6fd0..56f8825b8 100644 --- a/core/Credential.hpp +++ b/core/Credential.hpp @@ -16,6 +16,7 @@ #include "Constants.hpp" #include "TriviallyCopyable.hpp" +#include "CallContext.hpp" #include #include @@ -52,11 +53,11 @@ public: }; protected: - static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const MembershipCredential &credential); - static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const RevocationCredential &credential); - static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const TagCredential &credential); - static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const OwnershipCredential &credential); - static VerifyResult s_verify(const RuntimeEnvironment *RR, void *tPtr, const CapabilityCredential &credential); + static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const MembershipCredential &credential); + static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const RevocationCredential &credential); + static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const TagCredential &credential); + static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const OwnershipCredential &credential); + static VerifyResult s_verify(const RuntimeEnvironment *RR, CallContext &cc, const CapabilityCredential &credential); }; } // namespace ZeroTier diff --git a/core/Defragmenter.hpp b/core/Defragmenter.hpp index e79c4c5d1..e4c6994a9 100644 --- a/core/Defragmenter.hpp +++ b/core/Defragmenter.hpp @@ -50,7 +50,7 @@ template< unsigned int MFP = ZT_MAX_INCOMING_FRAGMENTS_PER_PATH, unsigned int GCS = (ZT_MAX_PACKET_FRAGMENTS * 2), unsigned int GCT = (ZT_MAX_PACKET_FRAGMENTS * 4), - typename P = SharedPtr > + typename P = SharedPtr< Path > > class Defragmenter { public: @@ -136,19 +136,19 @@ public: * @param fragmentDataSize Length of data in fragment's data.bytes (fragment's data.fields type is ignored) * @param fragmentNo Number of fragment (0..totalFragmentsExpected, non-inclusive) * @param totalFragmentsExpected Total number of expected fragments in this message or 0 to use cached value - * @param now Current time + * @param ts Current time * @param via If non-NULL this is the path on which this message fragment was received * @return Result code */ ZT_INLINE ResultCode assemble( const uint64_t messageId, - FCV &message, - SharedPtr &fragment, + FCV< Buf::Slice, MF > &message, + SharedPtr< Buf > &fragment, const unsigned int fragmentDataIndex, const unsigned int fragmentDataSize, const unsigned int fragmentNo, const unsigned int totalFragmentsExpected, - const int64_t now, + const int64_t ts, const P &via) { // Sanity checks for malformed fragments or invalid input parameters. @@ -210,7 +210,7 @@ public: return ERR_DUPLICATE_FRAGMENT; // Update last-activity timestamp for this entry, delaying GC. - e->lastUsed = now; + e->lastUsed = ts; // Learn total fragments expected if a value is given. Otherwise the cached // value gets used. This is to support the implementation of fragmentation @@ -344,11 +344,11 @@ private: unsigned int totalFragmentsExpected; unsigned int fragmentsReceived; P via; - FCV message; + FCV< Buf::Slice, MF > message; Mutex lock; }; - Map ::p_E> m_messages; + Map< uint64_t, Defragmenter< MF, MFP, GCS, GCT, P >::p_E > m_messages; RWMutex m_messages_l; }; diff --git a/core/Dictionary.cpp b/core/Dictionary.cpp index d43689f93..0139189b6 100644 --- a/core/Dictionary.cpp +++ b/core/Dictionary.cpp @@ -15,24 +15,24 @@ namespace ZeroTier { -Vector< uint8_t > &Dictionary::operator[](const char *const k) +ZT_MAYBE_UNUSED Vector< uint8_t > &Dictionary::operator[](const char *const k) { return m_entries[k]; } -const Vector< uint8_t > &Dictionary::operator[](const char *const k) const +ZT_MAYBE_UNUSED const Vector< uint8_t > &Dictionary::operator[](const char *const k) const { static const Vector< uint8_t > s_emptyEntry; const SortedMap< String, Vector< uint8_t > >::const_iterator e(m_entries.find(k)); return (e == m_entries.end()) ? s_emptyEntry : e->second; } -void Dictionary::add(const char *k, const Address &v) +ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const Address &v) { char tmp[ZT_ADDRESS_STRING_SIZE_MAX]; v.toString(tmp); add(k, tmp); } -void Dictionary::add(const char *k, const char *v) +ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const char *v) { Vector< uint8_t > &e = (*this)[k]; e.clear(); @@ -42,7 +42,7 @@ void Dictionary::add(const char *k, const char *v) } } -void Dictionary::add(const char *k, const void *data, unsigned int len) +ZT_MAYBE_UNUSED void Dictionary::add(const char *k, const void *data, unsigned int len) { Vector< uint8_t > &e = (*this)[k]; if (likely(len != 0)) { @@ -52,7 +52,7 @@ void Dictionary::add(const char *k, const void *data, unsigned int len) } } -uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const +ZT_MAYBE_UNUSED uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const { char tmp[32]; getS(k, tmp, sizeof(tmp)); @@ -61,7 +61,7 @@ uint64_t Dictionary::getUI(const char *k, uint64_t dfl) const return dfl; } -char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const +ZT_MAYBE_UNUSED char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const { if (cap == 0) // sanity check return v; @@ -84,10 +84,10 @@ char *Dictionary::getS(const char *k, char *v, const unsigned int cap) const return v; } -void Dictionary::clear() +ZT_MAYBE_UNUSED void Dictionary::clear() { m_entries.clear(); } -void Dictionary::encode(Vector< uint8_t > &out) const +ZT_MAYBE_UNUSED void Dictionary::encode(Vector< uint8_t > &out) const { out.clear(); for (SortedMap< String, Vector< uint8_t > >::const_iterator ti(m_entries.begin()); ti != m_entries.end(); ++ti) { @@ -98,7 +98,7 @@ void Dictionary::encode(Vector< uint8_t > &out) const } } -bool Dictionary::decode(const void *data, unsigned int len) +ZT_MAYBE_UNUSED bool Dictionary::decode(const void *data, unsigned int len) { clear(); String k; @@ -151,7 +151,7 @@ bool Dictionary::decode(const void *data, unsigned int len) return true; } -char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept +ZT_MAYBE_UNUSED char *Dictionary::arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept { if (bufSize < 17) { // sanity check buf[0] = 0; diff --git a/core/Dictionary.hpp b/core/Dictionary.hpp index 9db887e9c..4b9bac04b 100644 --- a/core/Dictionary.hpp +++ b/core/Dictionary.hpp @@ -81,7 +81,7 @@ public: * @param k Key to look up * @return Reference to value */ - Vector< uint8_t > &operator[](const char *k); + ZT_MAYBE_UNUSED Vector< uint8_t > &operator[](const char *k); /** * Get a const reference to a value @@ -89,18 +89,18 @@ public: * @param k Key to look up * @return Reference to value or to empty vector if not found */ - const Vector< uint8_t > &operator[](const char *k) const; + ZT_MAYBE_UNUSED const Vector< uint8_t > &operator[](const char *k) const; /** * @return Start of key->value pairs */ - ZT_INLINE const_iterator begin() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const_iterator begin() const noexcept { return m_entries.begin(); } /** * @return End of key->value pairs */ - ZT_INLINE const_iterator end() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const_iterator end() const noexcept { return m_entries.end(); } /** @@ -109,7 +109,7 @@ public: * @param k Key to set * @param v Integer to set, will be cast to uint64_t and stored as hex */ - ZT_INLINE void add(const char *const k, const uint64_t v) + ZT_MAYBE_UNUSED ZT_INLINE void add(const char *const k, const uint64_t v) { char buf[24]; add(k, Utils::hex((uint64_t)(v), buf)); @@ -121,7 +121,7 @@ public: * @param k Key to set * @param v Integer to set, will be cast to uint64_t and stored as hex */ - ZT_INLINE void add(const char *const k, const int64_t v) + ZT_MAYBE_UNUSED ZT_INLINE void add(const char *const k, const int64_t v) { char buf[24]; add(k, Utils::hex((uint64_t)(v), buf)); @@ -130,17 +130,17 @@ public: /** * Add an address in 10-digit hex string format */ - void add(const char *k, const Address &v); + ZT_MAYBE_UNUSED void add(const char *k, const Address &v); /** * Add a C string as a value */ - void add(const char *k, const char *v); + ZT_MAYBE_UNUSED void add(const char *k, const char *v); /** * Add a binary blob as a value */ - void add(const char *k, const void *data, unsigned int len); + ZT_MAYBE_UNUSED void add(const char *k, const void *data, unsigned int len); /** * Get an integer @@ -149,7 +149,7 @@ public: * @param dfl Default value (default: 0) * @return Value of key or default if not found */ - uint64_t getUI(const char *k, uint64_t dfl = 0) const; + ZT_MAYBE_UNUSED uint64_t getUI(const char *k, uint64_t dfl = 0) const; /** * Get a C string @@ -161,7 +161,7 @@ public: * @param v Buffer to hold string * @param cap Maximum size of string (including terminating null) */ - char *getS(const char *k, char *v, unsigned int cap) const; + ZT_MAYBE_UNUSED char *getS(const char *k, char *v, unsigned int cap) const; /** * Get an object supporting the marshal/unmarshal interface pattern @@ -172,7 +172,7 @@ public: * @return True if unmarshal was successful */ template< typename T > - ZT_INLINE bool getO(const char *k, T &obj) const + ZT_MAYBE_UNUSED ZT_INLINE bool getO(const char *k, T &obj) const { const Vector< uint8_t > &d = (*this)[k]; if (d.empty()) @@ -189,7 +189,7 @@ public: * @return True if successful */ template< typename T > - ZT_INLINE bool addO(const char *k, T &obj) + ZT_MAYBE_UNUSED ZT_INLINE bool addO(const char *k, T &obj) { Vector< uint8_t > &d = (*this)[k]; d.resize(T::marshalSizeMax()); @@ -205,18 +205,18 @@ public: /** * Erase all entries in dictionary */ - void clear(); + ZT_MAYBE_UNUSED void clear(); /** * @return Number of entries */ - ZT_INLINE unsigned int size() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned int size() const noexcept { return (unsigned int)m_entries.size(); } /** * @return True if dictionary is not empty */ - ZT_INLINE bool empty() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool empty() const noexcept { return m_entries.empty(); } /** @@ -224,7 +224,7 @@ public: * * @param out String encoded dictionary */ - void encode(Vector< uint8_t > &out) const; + ZT_MAYBE_UNUSED void encode(Vector< uint8_t > &out) const; /** * Decode a string encoded dictionary @@ -236,7 +236,7 @@ public: * @param len Length of data * @return True if dictionary was formatted correctly and valid, false on error */ - bool decode(const void *data, unsigned int len); + ZT_MAYBE_UNUSED bool decode(const void *data, unsigned int len); /** * Append a key=value pair to a buffer (vector or FCV) @@ -246,7 +246,7 @@ public: * @param v Value */ template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const bool v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const bool v) { s_appendKey(out, k); out.push_back((uint8_t)(v ? '1' : '0')); @@ -261,7 +261,7 @@ public: * @param v Value */ template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const Address v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const Address v) { s_appendKey(out, k); const uint64_t a = v.toInt(); @@ -287,7 +287,7 @@ public: * @param v Value */ template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const uint64_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint64_t v) { s_appendKey(out, k); char buf[17]; @@ -299,31 +299,31 @@ public: } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const int64_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int64_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const uint32_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint32_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const int32_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int32_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const uint16_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint16_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const int16_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int16_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const uint8_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const uint8_t v) { append(out, k, (uint64_t)v); } template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const int8_t v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const int8_t v) { append(out, k, (uint64_t)v); } /** @@ -334,7 +334,7 @@ public: * @param v Value */ template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const char *v) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const char *v) { if ((v) && (*v)) { s_appendKey(out, k); @@ -353,7 +353,7 @@ public: * @param vlen Value length in bytes */ template< typename V > - ZT_INLINE static void append(V &out, const char *const k, const void *const v, const unsigned int vlen) + ZT_MAYBE_UNUSED ZT_INLINE static void append(V &out, const char *const k, const void *const v, const unsigned int vlen) { s_appendKey(out, k); for (unsigned int i = 0; i < vlen; ++i) @@ -369,7 +369,7 @@ public: * @param pid Packet ID */ template< typename V > - static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid) + ZT_MAYBE_UNUSED static ZT_INLINE void appendPacketId(V &out, const char *const k, const uint64_t pid) { append(out, k, &pid, 8); } /** @@ -381,7 +381,7 @@ public: * @return Bytes appended or negative on error (return value of marshal()) */ template< typename V, typename T > - static ZT_INLINE int appendObject(V &out, const char *const k, const T &v) + ZT_MAYBE_UNUSED static ZT_INLINE int appendObject(V &out, const char *const k, const T &v) { uint8_t tmp[2048]; // large enough for any current object if (T::marshalSizeMax() > sizeof(tmp)) @@ -400,7 +400,7 @@ public: * @param sub Subscript index * @return Pointer to 'buf' */ - static char *arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept; + ZT_MAYBE_UNUSED static char *arraySubscript(char *buf, unsigned int bufSize, const char *name, const unsigned long sub) noexcept; private: template< typename V > diff --git a/core/Expect.hpp b/core/Expect.hpp index 3a053ad5b..c6d335003 100644 --- a/core/Expect.hpp +++ b/core/Expect.hpp @@ -68,7 +68,7 @@ public: private: // Each bucket contains a timestamp in units of the max expect duration. - std::atomic m_packetIdSent[ZT_EXPECT_BUCKETS]; + std::atomic< uint32_t > m_packetIdSent[ZT_EXPECT_BUCKETS]; }; } // namespace ZeroTier diff --git a/core/FCV.hpp b/core/FCV.hpp index 990c65648..ab3628d1f 100644 --- a/core/FCV.hpp +++ b/core/FCV.hpp @@ -81,7 +81,7 @@ public: /** * Clear this vector, destroying all content objects */ - ZT_INLINE void clear() + ZT_MAYBE_UNUSED ZT_INLINE void clear() { const unsigned int s = _s; _s = 0; @@ -94,51 +94,51 @@ public: * * @param v Target vector */ - ZT_INLINE void unsafeMoveTo(FCV &v) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void unsafeMoveTo(FCV &v) noexcept { Utils::copy(v._m, _m, (v._s = _s) * sizeof(T)); _s = 0; } - ZT_INLINE iterator begin() noexcept + ZT_MAYBE_UNUSED ZT_INLINE iterator begin() noexcept { return reinterpret_cast(_m); } - ZT_INLINE iterator end() noexcept + ZT_MAYBE_UNUSED ZT_INLINE iterator end() noexcept { return reinterpret_cast(_m) + _s; } - ZT_INLINE const_iterator begin() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const_iterator begin() const noexcept { return reinterpret_cast(_m); } - ZT_INLINE const_iterator end() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const_iterator end() const noexcept { return reinterpret_cast(_m) + _s; } - ZT_INLINE T &operator[](const unsigned int i) + ZT_MAYBE_UNUSED ZT_INLINE T &operator[](const unsigned int i) { if (likely(i < _s)) return reinterpret_cast(_m)[i]; throw Utils::OutOfRangeException; } - ZT_INLINE const T &operator[](const unsigned int i) const + ZT_MAYBE_UNUSED ZT_INLINE const T &operator[](const unsigned int i) const { if (likely(i < _s)) return reinterpret_cast(_m)[i]; throw Utils::OutOfRangeException; } - static constexpr unsigned int capacity() noexcept + ZT_MAYBE_UNUSED static constexpr unsigned int capacity() noexcept { return C; } - ZT_INLINE unsigned int size() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned int size() const noexcept { return _s; } - ZT_INLINE bool empty() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool empty() const noexcept { return (_s == 0); } - ZT_INLINE T *data() noexcept + ZT_MAYBE_UNUSED ZT_INLINE T *data() noexcept { return reinterpret_cast(_m); } - ZT_INLINE const T *data() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const T *data() const noexcept { return reinterpret_cast(_m); } /** @@ -148,7 +148,7 @@ public: * * @param v Value to push */ - ZT_INLINE void push_back(const T &v) + ZT_MAYBE_UNUSED ZT_INLINE void push_back(const T &v) { if (likely(_s < C)) new(reinterpret_cast(_m) + _s++) T(v); @@ -160,7 +160,7 @@ public: * * @return Reference to new item */ - ZT_INLINE T &push() + ZT_MAYBE_UNUSED ZT_INLINE T &push() { if (likely(_s < C)) { return *(new(reinterpret_cast(_m) + _s++) T()); @@ -174,7 +174,7 @@ public: * * @return Reference to new item */ - ZT_INLINE T &push(const T &v) + ZT_MAYBE_UNUSED ZT_INLINE T &push(const T &v) { if (likely(_s < C)) { return *(new(reinterpret_cast(_m) + _s++) T(v)); @@ -188,7 +188,7 @@ public: /** * Remove the last element if this vector is not empty */ - ZT_INLINE void pop_back() + ZT_MAYBE_UNUSED ZT_INLINE void pop_back() { if (likely(_s != 0)) (reinterpret_cast(_m) + --_s)->~T(); @@ -199,7 +199,7 @@ public: * * @param ns New size (clipped to C if larger than capacity) */ - ZT_INLINE void resize(unsigned int ns) + ZT_MAYBE_UNUSED ZT_INLINE void resize(unsigned int ns) { if (unlikely(ns > C)) throw Utils::OutOfRangeException; @@ -216,7 +216,7 @@ public: * * @param ns New size */ - ZT_INLINE void unsafeSetSize(unsigned int ns) + ZT_MAYBE_UNUSED ZT_INLINE void unsafeSetSize(unsigned int ns) { _s = ns; } /** @@ -228,7 +228,7 @@ public: * @param i Index to obtain as a reference, resizing if needed * @return Reference to value at this index */ - ZT_INLINE T &at(unsigned int i) + ZT_MAYBE_UNUSED ZT_INLINE T &at(unsigned int i) { if (i >= _s) { if (unlikely(i >= C)) @@ -250,7 +250,7 @@ public: * @param end Ending iterator (must be greater than start) */ template< typename X > - ZT_INLINE void assign(X start, const X &end) + ZT_MAYBE_UNUSED ZT_INLINE void assign(X start, const X &end) { const int l = std::min((int)std::distance(start, end), (int)C); if (l > 0) { @@ -262,7 +262,7 @@ public: } } - ZT_INLINE bool operator==(const FCV &v) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool operator==(const FCV &v) const noexcept { if (_s == v._s) { for (unsigned int i = 0; i < _s; ++i) { @@ -274,20 +274,20 @@ public: return false; } - ZT_INLINE bool operator!=(const FCV &v) const noexcept - { return (!(*this == v)); } + ZT_MAYBE_UNUSED ZT_INLINE bool operator!=(const FCV &v) const noexcept + { return *this != v; } - ZT_INLINE bool operator<(const FCV &v) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool operator<(const FCV &v) const noexcept { return std::lexicographical_compare(begin(), end(), v.begin(), v.end()); } - ZT_INLINE bool operator>(const FCV &v) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool operator>(const FCV &v) const noexcept { return (v < *this); } - ZT_INLINE bool operator<=(const FCV &v) const noexcept - { return !(v < *this); } + ZT_MAYBE_UNUSED ZT_INLINE bool operator<=(const FCV &v) const noexcept + { return v >= *this; } - ZT_INLINE bool operator>=(const FCV &v) const noexcept - { return !(*this < v); } + ZT_MAYBE_UNUSED ZT_INLINE bool operator>=(const FCV &v) const noexcept + { return *this >= v; } private: #ifdef _MSC_VER diff --git a/core/Fingerprint.hpp b/core/Fingerprint.hpp index c1de667a7..89aed3534 100644 --- a/core/Fingerprint.hpp +++ b/core/Fingerprint.hpp @@ -92,24 +92,6 @@ public: return true; } - /** - * Check for equality with best possible specificity. - * - * If both fingerprints have a hash, that is compared. Otherwise just the - * addresses are compared. - * - * @param fp Fingerprint to test - */ - ZT_INLINE bool bestSpecificityEquals(const ZT_Fingerprint &fp) const noexcept - { - if (address == fp.address) { - if (Utils::allZero(fp.hash, ZT_FINGERPRINT_HASH_SIZE) || Utils::allZero(hash, ZT_FINGERPRINT_HASH_SIZE)) - return true; - return (memcmp(hash, fp.hash, ZT_FINGERPRINT_HASH_SIZE) == 0); - } - return false; - } - ZT_INLINE void zero() noexcept { memoryZero(this); } diff --git a/core/Identity.cpp b/core/Identity.cpp index ef6140b7f..a7a9b9cac 100644 --- a/core/Identity.cpp +++ b/core/Identity.cpp @@ -15,12 +15,10 @@ #include "Identity.hpp" #include "SHA512.hpp" #include "Salsa20.hpp" -#include "Poly1305.hpp" #include "Utils.hpp" #include "Endpoint.hpp" #include "MIMC52.hpp" -#include #include #include @@ -31,7 +29,7 @@ namespace { // This is the memory-intensive hash function used to compute v0 identities from v0 public keys. #define ZT_V0_IDENTITY_GEN_MEMORY 2097152 -void identityV0ProofOfWorkFrankenhash(const void *const publicKey, unsigned int publicKeyBytes, void *const digest, void *const genmem) noexcept +void identityV0ProofOfWorkFrankenhash(const void *const restrict publicKey, unsigned int publicKeyBytes, void *const restrict digest, void *const restrict genmem) noexcept { // Digest publicKey[] to obtain initial digest SHA512(digest, publicKey, publicKeyBytes); @@ -68,7 +66,7 @@ void identityV0ProofOfWorkFrankenhash(const void *const publicKey, unsigned int struct identityV0ProofOfWorkCriteria { - ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *sb, char *gm) noexcept: digest(sb), genmem(gm) + ZT_INLINE identityV0ProofOfWorkCriteria(unsigned char *restrict sb, char *restrict gm) noexcept: digest(sb), genmem(gm) {} ZT_INLINE bool operator()(const uint8_t pub[ZT_C25519_COMBINED_PUBLIC_KEY_SIZE]) const noexcept diff --git a/core/InetAddress.cpp b/core/InetAddress.cpp index 29934c9b9..7d9f26dcc 100644 --- a/core/InetAddress.cpp +++ b/core/InetAddress.cpp @@ -27,7 +27,7 @@ const InetAddress InetAddress::LO4((const void *) ("\x7f\x00\x00\x01"), 4, 0); const InetAddress InetAddress::LO6((const void *) ("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"), 16, 0); const InetAddress InetAddress::NIL; -InetAddress::IpScope InetAddress::ipScope() const noexcept +ZT_MAYBE_UNUSED InetAddress::IpScope InetAddress::ipScope() const noexcept { switch (as.ss.ss_family) { @@ -40,17 +40,17 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept return ZT_IP_SCOPE_PSEUDOPRIVATE; // 6.0.0.0/8 (US Army) case 0x0a: return ZT_IP_SCOPE_PRIVATE; // 10.0.0.0/8 - case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) - case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) - case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) - case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense) - case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA) - case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) - case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) - case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) - case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) - case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) - case 0x38: // 56.0.0.0/8 (US Postal Service) + case 0x0b: //return IP_SCOPE_PSEUDOPRIVATE; // 11.0.0.0/8 (US DoD) + case 0x15: //return IP_SCOPE_PSEUDOPRIVATE; // 21.0.0.0/8 (US DDN-RVN) + case 0x16: //return IP_SCOPE_PSEUDOPRIVATE; // 22.0.0.0/8 (US DISA) + case 0x19: //return IP_SCOPE_PSEUDOPRIVATE; // 25.0.0.0/8 (UK Ministry of Defense) + case 0x1a: //return IP_SCOPE_PSEUDOPRIVATE; // 26.0.0.0/8 (US DISA) + case 0x1c: //return IP_SCOPE_PSEUDOPRIVATE; // 28.0.0.0/8 (US DSI-North) + case 0x1d: //return IP_SCOPE_PSEUDOPRIVATE; // 29.0.0.0/8 (US DISA) + case 0x1e: //return IP_SCOPE_PSEUDOPRIVATE; // 30.0.0.0/8 (US DISA) + case 0x33: //return IP_SCOPE_PSEUDOPRIVATE; // 51.0.0.0/8 (UK Department of Social Security) + case 0x37: //return IP_SCOPE_PSEUDOPRIVATE; // 55.0.0.0/8 (US DoD) + case 0x38: // 56.0.0.0/8 (US Postal Service) return ZT_IP_SCOPE_PSEUDOPRIVATE; case 0x64: if ((ip & 0xffc00000) == 0x64400000) return ZT_IP_SCOPE_PRIVATE; // 100.64.0.0/10 @@ -112,7 +112,7 @@ InetAddress::IpScope InetAddress::ipScope() const noexcept return ZT_IP_SCOPE_NONE; } -void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept +ZT_MAYBE_UNUSED void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept { memoryZero(this); if (ipLen == 4) { @@ -126,7 +126,7 @@ void InetAddress::set(const void *ipBytes, unsigned int ipLen, unsigned int port } } -bool InetAddress::isDefaultRoute() const noexcept +ZT_MAYBE_UNUSED bool InetAddress::isDefaultRoute() const noexcept { switch (as.ss.ss_family) { case AF_INET: @@ -145,7 +145,7 @@ bool InetAddress::isDefaultRoute() const noexcept } } -char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept +ZT_MAYBE_UNUSED char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept { char *p = toIpString(buf); if (*p) { @@ -156,7 +156,7 @@ char *InetAddress::toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noex return buf; } -char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept +ZT_MAYBE_UNUSED char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept { buf[0] = (char) 0; switch (as.ss.ss_family) { @@ -170,7 +170,7 @@ char *InetAddress::toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const no return buf; } -bool InetAddress::fromString(const char *ipSlashPort) noexcept +ZT_MAYBE_UNUSED bool InetAddress::fromString(const char *ipSlashPort) noexcept { char buf[64]; @@ -205,7 +205,7 @@ bool InetAddress::fromString(const char *ipSlashPort) noexcept return false; } -InetAddress InetAddress::netmask() const noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::netmask() const noexcept { InetAddress r(*this); switch (r.as.ss.ss_family) { @@ -229,7 +229,7 @@ InetAddress InetAddress::netmask() const noexcept return r; } -InetAddress InetAddress::broadcast() const noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::broadcast() const noexcept { if (as.ss.ss_family == AF_INET) { InetAddress r(*this); @@ -239,7 +239,7 @@ InetAddress InetAddress::broadcast() const noexcept return InetAddress(); } -InetAddress InetAddress::network() const noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::network() const noexcept { InetAddress r(*this); switch (r.as.ss.ss_family) { @@ -259,7 +259,7 @@ InetAddress InetAddress::network() const noexcept return r; } -bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept +ZT_MAYBE_UNUSED bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept { if (addr.as.ss.ss_family == as.ss.ss_family) { switch (as.ss.ss_family) { @@ -281,7 +281,7 @@ bool InetAddress::isEqualPrefix(const InetAddress &addr) const noexcept return false; } -bool InetAddress::containsAddress(const InetAddress &addr) const noexcept +ZT_MAYBE_UNUSED bool InetAddress::containsAddress(const InetAddress &addr) const noexcept { if (addr.as.ss.ss_family == as.ss.ss_family) { switch (as.ss.ss_family) { @@ -310,7 +310,7 @@ bool InetAddress::containsAddress(const InetAddress &addr) const noexcept return false; } -bool InetAddress::isNetwork() const noexcept +ZT_MAYBE_UNUSED bool InetAddress::isNetwork() const noexcept { switch (as.ss.ss_family) { case AF_INET: { @@ -342,7 +342,7 @@ bool InetAddress::isNetwork() const noexcept return false; } -int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept +ZT_MAYBE_UNUSED int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept { unsigned int port; switch (as.ss.ss_family) { @@ -369,7 +369,7 @@ int InetAddress::marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const no } } -int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept +ZT_MAYBE_UNUSED int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept { memoryZero(this); if (unlikely(len <= 0)) @@ -396,7 +396,7 @@ int InetAddress::unmarshal(const uint8_t *restrict data, const int len) noexcept } } -InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept { InetAddress r; r.as.sa_in6.sin6_family = AF_INET6; @@ -420,7 +420,7 @@ InetAddress InetAddress::makeIpv6LinkLocal(const MAC &mac) noexcept return r; } -InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress) noexcept { InetAddress r; r.as.sa_in6.sin6_family = AF_INET6; @@ -444,7 +444,7 @@ InetAddress InetAddress::makeIpv6rfc4193(uint64_t nwid, uint64_t zeroTierAddress return r; } -InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept +ZT_MAYBE_UNUSED InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) noexcept { nwid ^= (nwid >> 32U); InetAddress r; @@ -465,8 +465,8 @@ InetAddress InetAddress::makeIpv66plane(uint64_t nwid, uint64_t zeroTierAddress) } extern "C" { -extern const int ZT_AF_INET = (int)AF_INET; -extern const int ZT_AF_INET6 = (int)AF_INET6; +ZT_MAYBE_UNUSED extern const int ZT_AF_INET = (int)AF_INET; +ZT_MAYBE_UNUSED extern const int ZT_AF_INET6 = (int)AF_INET6; } } // namespace ZeroTier diff --git a/core/InetAddress.hpp b/core/InetAddress.hpp index 312a404a8..04a9a55b4 100644 --- a/core/InetAddress.hpp +++ b/core/InetAddress.hpp @@ -60,13 +60,6 @@ public: */ typedef ZT_InetAddress_IpScope IpScope; - // Hasher for unordered sets and maps in C++11 - struct Hasher - { - ZT_INLINE std::size_t operator()(const InetAddress &a) const noexcept - { return (std::size_t)a.hashCode(); } - }; - ZT_INLINE InetAddress() noexcept { memoryZero(this); } @@ -169,19 +162,13 @@ public: return *this; } - ZT_INLINE void clear() noexcept + ZT_MAYBE_UNUSED ZT_INLINE void clear() noexcept { memoryZero(this); } - /** - * @return Address family (ss_family in sockaddr_storage) - */ - ZT_INLINE uint8_t family() const noexcept - { return as.ss.ss_family; } - /** * @return IP scope classification (e.g. loopback, link-local, private, global) */ - IpScope ipScope() const noexcept; + ZT_MAYBE_UNUSED IpScope ipScope() const noexcept; /** * Set from a raw IP and port number @@ -190,14 +177,14 @@ public: * @param ipLen Length of IP address: 4 or 16 * @param port Port number or 0 for none */ - void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept; + ZT_MAYBE_UNUSED void set(const void *ipBytes, unsigned int ipLen, unsigned int port) noexcept; /** * Set the port component * * @param port Port, 0 to 65535 */ - ZT_INLINE void setPort(unsigned int port) noexcept + ZT_MAYBE_UNUSED ZT_INLINE void setPort(unsigned int port) noexcept { switch (as.ss.ss_family) { case AF_INET: @@ -212,14 +199,14 @@ public: /** * @return True if this network/netmask route describes a default route (e.g. 0.0.0.0/0) */ - bool isDefaultRoute() const noexcept; + ZT_MAYBE_UNUSED bool isDefaultRoute() const noexcept; /** * @return ASCII IP/port format representation */ - char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; + ZT_MAYBE_UNUSED char *toString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; - ZT_INLINE String toString() const + ZT_MAYBE_UNUSED ZT_INLINE String toString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toString(buf); @@ -229,9 +216,9 @@ public: /** * @return IP portion only, in ASCII string format */ - char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; + ZT_MAYBE_UNUSED char *toIpString(char buf[ZT_INETADDRESS_STRING_SIZE_MAX]) const noexcept; - ZT_INLINE String toIpString() const + ZT_MAYBE_UNUSED ZT_INLINE String toIpString() const { char buf[ZT_INETADDRESS_STRING_SIZE_MAX]; toIpString(buf); @@ -242,12 +229,12 @@ public: * @param ipSlashPort IP/port (port is optional, will be 0 if not included) * @return True if address appeared to be valid */ - bool fromString(const char *ipSlashPort) noexcept; + ZT_MAYBE_UNUSED bool fromString(const char *ipSlashPort) noexcept; /** * @return Port or 0 if no port component defined */ - ZT_INLINE unsigned int port() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned int port() const noexcept { switch (as.ss.ss_family) { case AF_INET: @@ -268,13 +255,13 @@ public: * * @return Netmask bits */ - ZT_INLINE unsigned int netmaskBits() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned int netmaskBits() const noexcept { return port(); } /** * @return True if netmask bits is valid for the address type */ - ZT_INLINE bool netmaskBitsValid() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool netmaskBitsValid() const noexcept { const unsigned int n = port(); switch (as.ss.ss_family) { @@ -294,7 +281,7 @@ public: * * @return Gateway metric */ - ZT_INLINE unsigned int metric() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned int metric() const noexcept { return port(); } /** @@ -302,7 +289,7 @@ public: * * @return Netmask such as 255.255.255.0 if this address is /24 (port field will be unchanged) */ - InetAddress netmask() const noexcept; + ZT_MAYBE_UNUSED InetAddress netmask() const noexcept; /** * Constructs a broadcast address from a network/netmask address @@ -312,14 +299,14 @@ public: * * @return Broadcast address (only IP portion is meaningful) */ - InetAddress broadcast() const noexcept; + ZT_MAYBE_UNUSED InetAddress broadcast() const noexcept; /** * Return the network -- a.k.a. the IP ANDed with the netmask * * @return Network e.g. 10.0.1.0/24 from 10.0.1.200/24 */ - InetAddress network() const noexcept; + ZT_MAYBE_UNUSED InetAddress network() const noexcept; /** * Test whether this IPv6 prefix matches the prefix of a given IPv6 address @@ -327,7 +314,7 @@ public: * @param addr Address to check * @return True if this IPv6 prefix matches the prefix of a given IPv6 address */ - bool isEqualPrefix(const InetAddress &addr) const noexcept; + ZT_MAYBE_UNUSED bool isEqualPrefix(const InetAddress &addr) const noexcept; /** * Test whether this IP/netmask contains this address @@ -335,24 +322,24 @@ public: * @param addr Address to check * @return True if this IP/netmask (route) contains this address */ - bool containsAddress(const InetAddress &addr) const noexcept; + ZT_MAYBE_UNUSED bool containsAddress(const InetAddress &addr) const noexcept; /** * @return True if this is an IPv4 address */ - ZT_INLINE bool isV4() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool isV4() const noexcept { return (as.ss.ss_family == AF_INET); } /** * @return True if this is an IPv6 address */ - ZT_INLINE bool isV6() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool isV6() const noexcept { return (as.ss.ss_family == AF_INET6); } /** * @return pointer to raw address bytes or NULL if not available */ - ZT_INLINE const void *rawIpData() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE const void *rawIpData() const noexcept { switch (as.ss.ss_family) { case AF_INET: @@ -367,7 +354,7 @@ public: /** * @return InetAddress containing only the IP portion of this address and a zero port, or NULL if not IPv4 or IPv6 */ - ZT_INLINE InetAddress ipOnly() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE InetAddress ipOnly() const noexcept { InetAddress r; switch (as.ss.ss_family) { @@ -389,7 +376,7 @@ public: * @param a InetAddress to compare again * @return True if only IP portions are equal (false for non-IP or null addresses) */ - ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool ipsEqual(const InetAddress &a) const noexcept { const uint8_t f = as.ss.ss_family; if (f == a.as.ss.ss_family) { @@ -410,7 +397,7 @@ public: * @param a InetAddress to compare again * @return True if only IP portions are equal (false for non-IP or null addresses) */ - ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept + ZT_MAYBE_UNUSED ZT_INLINE bool ipsEqual2(const InetAddress &a) const noexcept { const uint8_t f = as.ss.ss_family; if (f == a.as.ss.ss_family) { @@ -423,7 +410,7 @@ public: return false; } - ZT_INLINE unsigned long hashCode() const noexcept + ZT_MAYBE_UNUSED ZT_INLINE unsigned long hashCode() const noexcept { if (as.ss.ss_family == AF_INET) { return (unsigned long)Utils::hash32(((uint32_t)as.sa_in.sin_addr.s_addr + (uint32_t)as.sa_in.sin_port) ^ (uint32_t)Utils::s_mapNonce); @@ -445,20 +432,20 @@ public: * * @return True if everything after netmask bits is zero */ - bool isNetwork() const noexcept; + ZT_MAYBE_UNUSED bool isNetwork() const noexcept; /** * @return True if address family is non-zero */ - explicit ZT_INLINE operator bool() const noexcept + ZT_MAYBE_UNUSED explicit ZT_INLINE operator bool() const noexcept { return (as.ss.ss_family != 0); } - static constexpr int marshalSizeMax() noexcept + ZT_MAYBE_UNUSED static constexpr int marshalSizeMax() noexcept { return ZT_INETADDRESS_MARSHAL_SIZE_MAX; } - int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept; + ZT_MAYBE_UNUSED int marshal(uint8_t data[ZT_INETADDRESS_MARSHAL_SIZE_MAX]) const noexcept; - int unmarshal(const uint8_t *restrict data, int len) noexcept; + ZT_MAYBE_UNUSED int unmarshal(const uint8_t *restrict data, int len) noexcept; ZT_INLINE bool operator==(const InetAddress &a) const noexcept { @@ -512,7 +499,7 @@ public: * @param mac MAC address seed * @return IPv6 link-local address */ - static InetAddress makeIpv6LinkLocal(const MAC &mac) noexcept; + ZT_MAYBE_UNUSED static InetAddress makeIpv6LinkLocal(const MAC &mac) noexcept; /** * Compute private IPv6 unicast address from network ID and ZeroTier address @@ -574,64 +561,64 @@ public: } as; }; -static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_in *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_in6 *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(sockaddr_storage *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress *asInetAddress(ZT_InetAddress *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_in6 *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const sockaddr_storage *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress *asInetAddress(const ZT_InetAddress *const p) noexcept { return reinterpret_cast(p); } -static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_in &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_in6 &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(sockaddr_storage &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE InetAddress &asInetAddress(ZT_InetAddress &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_in6 &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const sockaddr_storage &p) noexcept { return *reinterpret_cast(&p); } -static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept +ZT_MAYBE_UNUSED static ZT_INLINE const InetAddress &asInetAddress(const ZT_InetAddress &p) noexcept { return *reinterpret_cast(&p); } } // namespace ZeroTier diff --git a/core/Locator.cpp b/core/Locator.cpp index 536a2b3e0..1c95b5173 100644 --- a/core/Locator.cpp +++ b/core/Locator.cpp @@ -24,7 +24,7 @@ Locator::Locator(const char *const str) noexcept : __refCount(0) { if (!fromString(str)) { - m_ts = 0; + m_revision = 0; m_signer.zero(); m_endpoints.clear(); m_signature.clear(); @@ -46,9 +46,9 @@ bool Locator::add(const Endpoint &ep, const SharedPtr< const EndpointAttributes return false; } -bool Locator::sign(const int64_t ts, const Identity &id) noexcept +bool Locator::sign(const int64_t rev, const Identity &id) noexcept { - m_ts = ts; + m_revision = rev; m_signer = id.fingerprint(); m_sortEndpoints(); @@ -67,7 +67,7 @@ bool Locator::sign(const int64_t ts, const Identity &id) noexcept bool Locator::verify(const Identity &id) const noexcept { try { - if ((m_ts > 0) && (m_signer == id.fingerprint())) { + if ((m_revision > 0) && (m_signer == id.fingerprint())) { uint8_t signdata[ZT_LOCATOR_MARSHAL_SIZE_MAX]; const unsigned int signlen = marshal(signdata, true); return id.verify(signdata, signlen, m_signature.data(), m_signature.size()); @@ -101,7 +101,7 @@ bool Locator::fromString(const char *s) noexcept int Locator::marshal(uint8_t data[ZT_LOCATOR_MARSHAL_SIZE_MAX], const bool excludeSignature) const noexcept { - Utils::storeBigEndian(data, (uint64_t) m_ts); + Utils::storeBigEndian(data, (uint64_t) m_revision); int p = 8; int l = m_signer.marshal(data + p); @@ -143,7 +143,7 @@ int Locator::unmarshal(const uint8_t *data, const int len) noexcept { if (unlikely(len < 8)) return -1; - m_ts = (int64_t)Utils::loadBigEndian(data); + m_revision = (int64_t)Utils::loadBigEndian(data); int p = 8; int l = m_signer.unmarshal(data + p, len - p); diff --git a/core/Locator.hpp b/core/Locator.hpp index c453c308f..1211dd51e 100644 --- a/core/Locator.hpp +++ b/core/Locator.hpp @@ -106,13 +106,13 @@ public: }; ZT_INLINE Locator() noexcept: - m_ts(0) + m_revision(0) {} explicit Locator(const char *const str) noexcept; ZT_INLINE Locator(const Locator &loc) noexcept: - m_ts(loc.m_ts), + m_revision(loc.m_revision), m_signer(loc.m_signer), m_endpoints(loc.m_endpoints), m_signature(loc.m_signature), @@ -122,8 +122,8 @@ public: /** * @return Timestamp (a.k.a. revision number) set by Location signer */ - ZT_INLINE int64_t timestamp() const noexcept - { return m_ts; } + ZT_INLINE int64_t revision() const noexcept + { return m_revision; } /** * @return Fingerprint of identity that signed this locator @@ -164,7 +164,7 @@ public: * @param id Identity that includes private key * @return True if signature successful */ - bool sign(int64_t ts, const Identity &id) noexcept; + bool sign(int64_t rev, const Identity &id) noexcept; /** * Verify this Locator's validity and signature @@ -197,7 +197,7 @@ public: bool fromString(const char *s) noexcept; explicit ZT_INLINE operator bool() const noexcept - { return m_ts > 0; } + { return m_revision > 0; } static constexpr int marshalSizeMax() noexcept { return ZT_LOCATOR_MARSHAL_SIZE_MAX; } @@ -207,7 +207,7 @@ public: ZT_INLINE bool operator==(const Locator &l) const noexcept { const unsigned long es = (unsigned long)m_endpoints.size(); - if ((m_ts == l.m_ts) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) { + if ((m_revision == l.m_revision) && (m_signer == l.m_signer) && (es == (unsigned long)l.m_endpoints.size()) && (m_signature == l.m_signature)) { for(unsigned long i=0;i > > m_endpoints; FCV< uint8_t, ZT_SIGNATURE_BUFFER_SIZE > m_signature; diff --git a/core/Member.cpp b/core/Member.cpp index 4c3a6fbcd..db4dff9b9 100644 --- a/core/Member.cpp +++ b/core/Member.cpp @@ -28,7 +28,7 @@ Member::Member() : { } -void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int64_t now, const SharedPtr< Peer > &to, const NetworkConfig &nconf) +void Member::pushCredentials(const RuntimeEnvironment *RR, CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf) { if (!nconf.com) // sanity check return; @@ -112,7 +112,7 @@ void Member::pushCredentials(const RuntimeEnvironment *RR, void *tPtr, const int } #endif - m_lastPushedCredentials = now; + m_lastPushedCredentials = cc.ticks; } void Member::clean(const NetworkConfig &nconf) @@ -122,31 +122,31 @@ void Member::clean(const NetworkConfig &nconf) m_cleanCredImpl< OwnershipCredential >(nconf, m_remoteCoos); } -Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com) +Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com) { const int64_t newts = com.timestamp(); if (newts <= m_comRevocationThreshold) { - RR->t->credentialRejected(tPtr, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); + RR->t->credentialRejected(cc, 0xd9992121, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); return ADD_REJECTED; } const int64_t oldts = m_com.timestamp(); if (newts < oldts) { - RR->t->credentialRejected(tPtr, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); + RR->t->credentialRejected(cc, 0xd9928192, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); return ADD_REJECTED; } if ((newts == oldts) && (m_com == com)) return ADD_ACCEPTED_REDUNDANT; - switch (com.verify(RR, tPtr)) { + switch (com.verify(RR, cc)) { default: - RR->t->credentialRejected(tPtr, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); + RR->t->credentialRejected(cc, 0x0f198241, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); return Member::ADD_REJECTED; case Credential::VERIFY_OK: m_com = com; return ADD_ACCEPTED_NEW; case Credential::VERIFY_BAD_SIGNATURE: - RR->t->credentialRejected(tPtr, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED); + RR->t->credentialRejected(cc, 0xbaf0aaaa, com.networkId(), sourcePeerIdentity, com.id(), com.timestamp(), ZT_CREDENTIAL_TYPE_COM, ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED); return ADD_REJECTED; case Credential::VERIFY_NEED_IDENTITY: return ADD_DEFERRED_FOR_WHOIS; @@ -159,15 +159,15 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl( Map< uint32_t, C > &remoteCreds, const Map< uint64_t, int64_t > &revocations, const RuntimeEnvironment *const RR, - void *const tPtr, + CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const C &cred) { typename Map< uint32_t, C >::const_iterator rc(remoteCreds.find(cred.id())); if (rc != remoteCreds.end()) { - if (rc->second.timestamp() > cred.timestamp()) { - RR->t->credentialRejected(tPtr, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); + if (rc->second.revision() > cred.revision()) { + RR->t->credentialRejected(cc, 0x40000001, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_OLDER_THAN_LATEST); return Member::ADD_REJECTED; } if (rc->second == cred) @@ -175,14 +175,14 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl( } typename Map< uint64_t, int64_t >::const_iterator rt(revocations.find(Member::credentialKey(C::credentialType(), cred.id()))); - if ((rt != revocations.end()) && (rt->second >= cred.timestamp())) { - RR->t->credentialRejected(tPtr, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); + if ((rt != revocations.end()) && (rt->second >= cred.revision())) { + RR->t->credentialRejected(cc, 0x24248124, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED); return Member::ADD_REJECTED; } - switch (cred.verify(RR, tPtr)) { + switch (cred.verify(RR, cc)) { default: - RR->t->credentialRejected(tPtr, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.timestamp(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); + RR->t->credentialRejected(cc, 0x01feba012, nconf.networkId, sourcePeerIdentity, cred.id(), cred.revision(), C::credentialType(), ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); return Member::ADD_REJECTED; case 0: if (rc == remoteCreds.end()) @@ -193,21 +193,21 @@ static ZT_INLINE Member::AddCredentialResult _addCredImpl( } } -Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag) -{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, tag); } +Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag) +{ return _addCredImpl< TagCredential >(m_remoteTags, m_revocations, RR, cc, sourcePeerIdentity, nconf, tag); } -Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap) -{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, cap); } +Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap) +{ return _addCredImpl< CapabilityCredential >(m_remoteCaps, m_revocations, RR, cc, sourcePeerIdentity, nconf, cap); } -Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo) -{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, RR, tPtr, sourcePeerIdentity, nconf, coo); } +Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo) +{ return _addCredImpl< OwnershipCredential >(m_remoteCoos, m_revocations, RR, cc, sourcePeerIdentity, nconf, coo); } -Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, void *tPtr, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev) +Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev) { int64_t *rt; - switch (rev.verify(RR, tPtr)) { + switch (rev.verify(RR, cc)) { default: - RR->t->credentialRejected(tPtr, 0x938fffff, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); + RR->t->credentialRejected(cc, 0x938fffff, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); return ADD_REJECTED; case 0: { const ZT_CredentialType ct = rev.typeBeingRevoked(); @@ -229,7 +229,7 @@ Member::AddCredentialResult Member::addCredential(const RuntimeEnvironment *RR, } return ADD_ACCEPTED_REDUNDANT; default: - RR->t->credentialRejected(tPtr, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); + RR->t->credentialRejected(cc, 0x0bbbb1a4, nconf.networkId, sourcePeerIdentity, rev.id(), 0, ZT_CREDENTIAL_TYPE_REVOCATION, ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID); return ADD_REJECTED; } } diff --git a/core/Member.hpp b/core/Member.hpp index c4a76939f..3f6099035 100644 --- a/core/Member.hpp +++ b/core/Member.hpp @@ -26,6 +26,7 @@ namespace ZeroTier { class RuntimeEnvironment; + class Network; /** @@ -51,18 +52,16 @@ public: /** * Send COM and other credentials to this peer * - * @param RR Runtime environment - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param now Current time * @param to Peer identity * @param nconf My network config */ - void pushCredentials(const RuntimeEnvironment *RR,void *tPtr,int64_t now,const SharedPtr &to,const NetworkConfig &nconf); + void pushCredentials(const RuntimeEnvironment *RR, CallContext &cc, const SharedPtr< Peer > &to, const NetworkConfig &nconf); /** * @return Time we last pushed credentials to this member */ - ZT_INLINE int64_t lastPushedCredentials() const noexcept { return m_lastPushedCredentials; } + ZT_INLINE int64_t lastPushedCredentials() const noexcept + { return m_lastPushedCredentials; } /** * Get a remote member's tag (if we have it) @@ -74,7 +73,7 @@ public: ZT_INLINE const TagCredential *getTag(const NetworkConfig &nconf, const uint32_t id) const noexcept { Map< uint32_t, TagCredential >::const_iterator t(m_remoteTags.find(id)); - return (((t != m_remoteTags.end())&&(m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0); + return (((t != m_remoteTags.end()) && (m_isCredentialTimestampValid(nconf, t->second))) ? &(t->second) : (TagCredential *)0); } /** @@ -87,7 +86,8 @@ public: /** * Generates a key for internal use in indexing credentials by type and credential ID */ - static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType &t,const uint32_t i) noexcept { return (((uint64_t)t << 32U) | (uint64_t)i); } + static ZT_INLINE uint64_t credentialKey(const ZT_CredentialType &t, const uint32_t i) noexcept + { return (((uint64_t)t << 32U) | (uint64_t)i); } /** * Check whether the peer represented by this Membership owns a given address @@ -97,12 +97,12 @@ public: * @param r Resource to check * @return True if this peer has a certificate of ownership for the given resource */ - template + template< typename T > ZT_INLINE bool peerOwnsAddress(const NetworkConfig &nconf, const T &r) const noexcept { if (m_isUnspoofableAddress(nconf, r)) return true; - for(Map< uint32_t,OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) { + for (Map< uint32_t, OwnershipCredential >::const_iterator i(m_remoteCoos.begin()); i != m_remoteCoos.end(); ++i) { if (m_isCredentialTimestampValid(nconf, i->second) && (i->second.owns(r))) return true; } @@ -145,36 +145,38 @@ public: return false; } - AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const MembershipCredential &com); - AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const TagCredential &tag); - AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const CapabilityCredential &cap); - AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const OwnershipCredential &coo); - AddCredentialResult addCredential(const RuntimeEnvironment *RR,void *tPtr,const Identity &sourcePeerIdentity,const NetworkConfig &nconf,const RevocationCredential &rev); + AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const MembershipCredential &com); + AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const TagCredential &tag); + AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const CapabilityCredential &cap); + AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const OwnershipCredential &coo); + AddCredentialResult addCredential(const RuntimeEnvironment *RR, CallContext &cc, const Identity &sourcePeerIdentity, const NetworkConfig &nconf, const RevocationCredential &rev); private: // This returns true if a resource is an IPv6 NDP-emulated address. These embed the ZT // address of the peer and therefore cannot be spoofed, causing peerOwnsAddress() to // always return true for them. A certificate is not required for these. - ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept { return false; } + ZT_INLINE bool m_isUnspoofableAddress(const NetworkConfig &nconf, const MAC &m) const noexcept + { return false; } + bool m_isUnspoofableAddress(const NetworkConfig &nconf, const InetAddress &ip) const noexcept; // This compares the remote credential's timestamp to the timestamp in our network config // plus or minus the permitted maximum timestamp delta. - template + template< typename C > ZT_INLINE bool m_isCredentialTimestampValid(const NetworkConfig &nconf, const C &remoteCredential) const noexcept { - const int64_t ts = remoteCredential.timestamp(); + const int64_t ts = remoteCredential.revision(); if (((ts >= nconf.timestamp) ? (ts - nconf.timestamp) : (nconf.timestamp - ts)) <= nconf.credentialTimeMaxDelta) { Map< uint64_t, int64_t >::const_iterator threshold(m_revocations.find(credentialKey(C::credentialType(), remoteCredential.id()))); - return ((threshold == m_revocations.end())||(ts > threshold->second)); + return ((threshold == m_revocations.end()) || (ts > threshold->second)); } return false; } - template - ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map &remoteCreds) + template< typename C > + ZT_INLINE void m_cleanCredImpl(const NetworkConfig &nconf, Map< uint32_t, C > &remoteCreds) { - for(typename Map::iterator i(remoteCreds.begin());i!=remoteCreds.end();) { + for (typename Map< uint32_t, C >::iterator i(remoteCreds.begin()); i != remoteCreds.end();) { if (!m_isCredentialTimestampValid(nconf, i->second)) remoteCreds.erase(i++); else ++i; @@ -188,24 +190,24 @@ private: int64_t m_lastPushedCredentials; // COM timestamps at which we last agreed-- used to memo-ize agreement and avoid having to recompute constantly. - int64_t m_comAgreementLocalTimestamp,m_comAgreementRemoteTimestamp; + int64_t m_comAgreementLocalTimestamp, m_comAgreementRemoteTimestamp; // Remote member's latest network COM MembershipCredential m_com; // Revocations by credentialKey() - Map m_revocations; + Map< uint64_t, int64_t > m_revocations; // Remote credentials that we have received from this member (and that are valid) - Map m_remoteTags; - Map m_remoteCaps; - Map m_remoteCoos; + Map< uint32_t, TagCredential > m_remoteTags; + Map< uint32_t, CapabilityCredential > m_remoteCaps; + Map< uint32_t, OwnershipCredential > m_remoteCoos; public: class CapabilityIterator { public: - ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept : + ZT_INLINE CapabilityIterator(Member &m, const NetworkConfig &nconf) noexcept: m_hti(m.m_remoteCaps.begin()), m_parent(m), m_nconf(nconf) @@ -215,7 +217,7 @@ public: ZT_INLINE CapabilityCredential *next() noexcept { while (m_hti != m_parent.m_remoteCaps.end()) { - Map< uint32_t,CapabilityCredential >::iterator i(m_hti++); + Map< uint32_t, CapabilityCredential >::iterator i(m_hti++); if (m_parent.m_isCredentialTimestampValid(m_nconf, i->second)) return &(i->second); } @@ -223,7 +225,7 @@ public: } private: - Map< uint32_t,CapabilityCredential >::iterator m_hti; + Map< uint32_t, CapabilityCredential >::iterator m_hti; Member &m_parent; const NetworkConfig &m_nconf; }; diff --git a/core/MembershipCredential.hpp b/core/MembershipCredential.hpp index a744e87ed..c631fdd3c 100644 --- a/core/MembershipCredential.hpp +++ b/core/MembershipCredential.hpp @@ -133,6 +133,9 @@ public: */ ZT_INLINE int64_t timestamp() const noexcept { return m_timestamp; } + ZT_INLINE int64_t revision() const noexcept + { return m_timestamp; } + /** * @return Maximum allowed difference between timestamps */ @@ -177,7 +180,7 @@ public: * @param RR Runtime environment for looking up peers * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return s_verify(RR, tPtr, *this); } + ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const { return s_verify(RR, cc, *this); } // NOTE: right now we use v1 serialization format which works with both ZeroTier 1.x and 2.x. V2 format // will be switched on once 1.x is pretty much dead and out of support. diff --git a/core/Meter.hpp b/core/Meter.hpp index 2e8f427f9..7c784d167 100644 --- a/core/Meter.hpp +++ b/core/Meter.hpp @@ -43,28 +43,25 @@ public: * * @param now Start time */ - ZT_INLINE Meter() noexcept : - m_counts(), - m_totalExclCounts(0), - m_bucket(0) + ZT_INLINE Meter() noexcept {} /** * Add a measurement * - * @param now Current time + * @param ts Timestamp for measurement * @param count Count of items (usually bytes) */ - ZT_INLINE void log(const int64_t now, uint64_t count) noexcept + ZT_INLINE void log(const int64_t ts, const uint64_t count) noexcept { // We log by choosing a log bucket based on the current time in units modulo // the log size and then if it's a new bucket setting it or otherwise adding // to it. - const unsigned long bucket = ((unsigned long)(now / TUNIT)) % LSIZE; - if (m_bucket.exchange(bucket) != bucket) { - m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count)); + const unsigned long bucket = ((unsigned long)(ts / TUNIT)) % LSIZE; + if (m_bucket.exchange(bucket, std::memory_order_relaxed) != bucket) { + m_totalExclCounts.fetch_add(m_counts[bucket].exchange(count, std::memory_order_relaxed), std::memory_order_relaxed); } else { - m_counts[bucket].fetch_add(count); + m_counts[bucket].fetch_add(count, std::memory_order_relaxed); } } @@ -79,9 +76,9 @@ public: { total = 0; for (unsigned long i = 0;i < LSIZE;++i) - total += m_counts[i].load(); + total += m_counts[i].load(std::memory_order_relaxed); rate = (double) total / (double) LSIZE; - total += m_totalExclCounts.load(); + total += m_totalExclCounts.load(std::memory_order_relaxed); } private: diff --git a/core/Network.cpp b/core/Network.cpp index ce216bbce..4c00f7de2 100644 --- a/core/Network.cpp +++ b/core/Network.cpp @@ -538,7 +538,7 @@ _doZtFilterResult _doZtFilter( const ZeroTier::MulticastGroup Network::BROADCAST(ZeroTier::MAC(0xffffffffffffULL), 0); -Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf) : +Network::Network(const RuntimeEnvironment *renv, CallContext &cc, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf) : RR(renv), m_uPtr(uptr), m_id(nwid), @@ -552,7 +552,7 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons m_controllerFingerprint = controllerFingerprint; if (nconf) { - this->setConfiguration(tPtr, *nconf, false); + this->setConfiguration(cc, *nconf, false); m_lastConfigUpdate = 0; // still want to re-request since it's likely outdated } else { uint64_t tmp[2]; @@ -562,14 +562,14 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons bool got = false; try { Dictionary dict; - Vector< uint8_t > nconfData(RR->store->get(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1)); + Vector< uint8_t > nconfData(RR->store->get(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1)); if (nconfData.size() > 2) { nconfData.push_back(0); if (dict.decode(nconfData.data(), (unsigned int)nconfData.size())) { try { ScopedPtr< NetworkConfig > nconf2(new NetworkConfig()); if (nconf2->fromDictionary(dict)) { - this->setConfiguration(tPtr, *nconf2, false); + this->setConfiguration(cc, *nconf2, false); m_lastConfigUpdate = 0; // still want to re-request an update since it's likely outdated got = true; } @@ -579,13 +579,13 @@ Network::Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, cons } catch (...) {} if (!got) - RR->store->put(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, "\n", 1); + RR->store->put(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, "\n", 1); } if (!m_portInitialized) { ZT_VirtualNetworkConfig ctmp; m_externalConfig(&ctmp); - RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); + RR->cb.virtualNetworkConfigFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); m_portInitialized = true; } } @@ -604,12 +604,12 @@ Network::~Network() // This is done in Node::leave() so we can pass tPtr properly //RR->node->configureVirtualNetworkPort((void *)0,_id,&_uPtr,ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY,&ctmp); } else { - RR->node->configureVirtualNetworkPort(nullptr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp); + RR->cb.virtualNetworkConfigFunction(reinterpret_cast(RR->node), RR->uPtr, nullptr, m_id, &m_uPtr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DOWN, &ctmp); } } bool Network::filterOutgoingPacket( - void *tPtr, + CallContext &cc, const bool noTee, const Address &ztSource, const Address &ztDest, @@ -625,7 +625,7 @@ bool Network::filterOutgoingPacket( Address ztFinalDest(ztDest); int localCapabilityIndex = -1; int accept = 0; - Address cc; + Address ccNodeAddress; unsigned int ccLength = 0; bool ccWatch = false; @@ -640,7 +640,7 @@ bool Network::filterOutgoingPacket( membership = nullptr; } - switch (_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { + switch (_doZtFilter(RR, rrl, m_config, membership, false, ztSource, ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, ccNodeAddress, ccLength, ccWatch, qosBucket)) { case DOZTFILTER_NO_MATCH: { for (unsigned int c = 0; c < m_config.capabilityCount; ++c) { @@ -683,7 +683,7 @@ bool Network::filterOutgoingPacket( break; case DOZTFILTER_DROP: - RR->t->networkFilter(tPtr, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0); + RR->t->networkFilter(cc, 0xadea5a2a, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, 0); return false; case DOZTFILTER_REDIRECT: // interpreted as ACCEPT but ztFinalDest will have been changed in _doZtFilter() @@ -697,7 +697,7 @@ bool Network::filterOutgoingPacket( } if (accept != 0) { - if ((!noTee) && (cc)) { + if ((!noTee) && (ccNodeAddress)) { // TODO /* Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -733,16 +733,16 @@ bool Network::filterOutgoingPacket( if (localCapabilityIndex >= 0) { const CapabilityCredential &cap = m_config.capabilities[localCapabilityIndex]; - RR->t->networkFilter(tPtr, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); + RR->t->networkFilter(cc, 0x56ff1a93, m_id, rrl.l, crrl.l, cap.id(), cap.timestamp(), ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); } else { - RR->t->networkFilter(tPtr, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); + RR->t->networkFilter(cc, 0x112fbbab, m_id, rrl.l, nullptr, 0, 0, ztSource, ztDest, macSource, macDest, (uint16_t)frameLen, frameData, (uint16_t)etherType, (uint16_t)vlanId, noTee, false, accept); } return (accept != 0); } int Network::filterIncomingPacket( - void *tPtr, + CallContext &cc, const SharedPtr< Peer > &sourcePeer, const Address &ztDest, const MAC &macSource, @@ -755,7 +755,7 @@ int Network::filterIncomingPacket( Address ztFinalDest(ztDest); Trace::RuleResultLog rrl, crrl; int accept = 0; - Address cc; + Address ccNodeAddress; unsigned int ccLength = 0; bool ccWatch = false; const CapabilityCredential *c = nullptr; @@ -767,7 +767,7 @@ int Network::filterIncomingPacket( Member &membership = m_memberships[sourcePeer->address()]; - switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, cc, ccLength, ccWatch, qosBucket)) { + switch (_doZtFilter(RR, rrl, m_config, &membership, true, sourcePeer->address(), ztFinalDest, macSource, macDest, frameData, frameLen, etherType, vlanId, m_config.rules, m_config.ruleCount, ccNodeAddress, ccLength, ccWatch, qosBucket)) { case DOZTFILTER_NO_MATCH: { Member::CapabilityIterator mci(membership, m_config); @@ -825,7 +825,7 @@ int Network::filterIncomingPacket( } if (accept) { - if (cc) { + if (ccNodeAddress) { // TODO /* Packet outp(cc,RR->identity.address(),Packet::VERB_EXT_FRAME); @@ -865,13 +865,13 @@ int Network::filterIncomingPacket( return accept; } -void Network::multicastSubscribe(void *tPtr, const MulticastGroup &mg) +void Network::multicastSubscribe(CallContext &cc, const MulticastGroup &mg) { Mutex::Lock l(m_myMulticastGroups_l); if (!std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) { m_myMulticastGroups.insert(std::upper_bound(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg), mg); Mutex::Lock l2(m_memberships_l); - m_announceMulticastGroups(tPtr, true); + m_announceMulticastGroups(cc.tPtr, true); } } @@ -883,7 +883,7 @@ void Network::multicastUnsubscribe(const MulticastGroup &mg) m_myMulticastGroups.erase(i); } -uint64_t Network::handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size) +uint64_t Network::handleConfigChunk(CallContext &cc, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size) { // If the controller's full fingerprint is known or was explicitly specified on join(), // require that the controller's identity match. Otherwise learn it. @@ -1027,7 +1027,7 @@ uint64_t Network::handleConfigChunk(void *tPtr, uint64_t packetId, const SharedP #endif } -int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk) +int Network::setConfiguration(CallContext &cc, const NetworkConfig &nconf, bool saveToDisk) { if (m_destroyed) return 0; @@ -1048,7 +1048,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT Mutex::Lock l1(m_config_l); m_config = nconf; - m_lastConfigUpdate = RR->node->now(); + m_lastConfigUpdate = cc.ticks; _netconfFailure = NETCONF_FAILURE_NONE; oldPortInitialized = m_portInitialized; @@ -1057,7 +1057,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT m_externalConfig(&ctmp); } - RR->node->configureVirtualNetworkPort(tPtr, m_id, &m_uPtr, (oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); + RR->cb.virtualNetworkConfigFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, nconf.networkId, &m_uPtr, (oldPortInitialized) ? ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_CONFIG_UPDATE : ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_UP, &ctmp); if (saveToDisk) { try { @@ -1068,7 +1068,7 @@ int Network::setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveT tmp[1] = 0; Vector< uint8_t > d2; d.encode(d2); - RR->store->put(tPtr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, d2.data(), (unsigned int)d2.size()); + RR->store->put(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1, d2.data(), (unsigned int)d2.size()); } } catch (...) {} } @@ -1095,13 +1095,13 @@ bool Network::gate(void *tPtr, const SharedPtr< Peer > &peer) noexcept return false; } -void Network::doPeriodicTasks(void *tPtr, const int64_t now) +void Network::doPeriodicTasks(CallContext &cc) { if (m_destroyed) return; - if ((now - m_lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY) - m_requestConfiguration(tPtr); + if ((cc.ticks - m_lastConfigUpdate) >= ZT_NETWORK_AUTOCONF_DELAY) + m_requestConfiguration(cc); { Mutex::Lock l1(m_memberships_l); @@ -1157,31 +1157,31 @@ void Network::learnBridgeRoute(const MAC &mac, const Address &addr) } } -Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com) +Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com) { if (com.networkId() != m_id) return Member::ADD_REJECTED; Mutex::Lock _l(m_memberships_l); - return m_memberships[com.issuedTo().address].addCredential(RR, tPtr, sourcePeerIdentity, m_config, com); + return m_memberships[com.issuedTo().address].addCredential(RR, cc, sourcePeerIdentity, m_config, com); } -Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap) +Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap) { if (cap.networkId() != m_id) return Member::ADD_REJECTED; Mutex::Lock _l(m_memberships_l); - return m_memberships[cap.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, cap); + return m_memberships[cap.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, cap); } -Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag) +Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag) { if (tag.networkId() != m_id) return Member::ADD_REJECTED; Mutex::Lock _l(m_memberships_l); - return m_memberships[tag.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, tag); + return m_memberships[tag.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, tag); } -Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev) +Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev) { if (rev.networkId() != m_id) return Member::ADD_REJECTED; @@ -1189,7 +1189,7 @@ Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &s Mutex::Lock l1(m_memberships_l); Member &m = m_memberships[rev.target()]; - const Member::AddCredentialResult result = m.addCredential(RR, tPtr, sourcePeerIdentity, m_config, rev); + const Member::AddCredentialResult result = m.addCredential(RR, cc, sourcePeerIdentity, m_config, rev); if ((result == Member::ADD_ACCEPTED_NEW) && (rev.fastPropagate())) { // TODO @@ -1215,22 +1215,21 @@ Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &s return result; } -Member::AddCredentialResult Network::addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo) +Member::AddCredentialResult Network::addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo) { if (coo.networkId() != m_id) return Member::ADD_REJECTED; Mutex::Lock _l(m_memberships_l); - return m_memberships[coo.issuedTo()].addCredential(RR, tPtr, sourcePeerIdentity, m_config, coo); + return m_memberships[coo.issuedTo()].addCredential(RR, cc, sourcePeerIdentity, m_config, coo); } -void Network::pushCredentials(void *tPtr, const SharedPtr< Peer > &to, const int64_t now) +void Network::pushCredentials(CallContext &cc, const SharedPtr< Peer > &to) { const int64_t tout = std::min(m_config.credentialTimeMaxDelta, m_config.com.timestampMaxDelta()); Mutex::Lock _l(m_memberships_l); Member &m = m_memberships[to->address()]; - if (((now - m.lastPushedCredentials()) + 5000) >= tout) { - m.pushCredentials(RR, tPtr, now, to, m_config); - } + if (((cc.ticks - m.lastPushedCredentials()) + 5000) >= tout) + m.pushCredentials(RR, cc, to, m_config); } void Network::destroy() @@ -1248,7 +1247,7 @@ void Network::externalConfig(ZT_VirtualNetworkConfig *ec) const m_externalConfig(ec); } -void Network::m_requestConfiguration(void *tPtr) +void Network::m_requestConfiguration(CallContext &cc) { if (m_destroyed) return; @@ -1261,7 +1260,7 @@ void Network::m_requestConfiguration(void *tPtr) ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); nconf->networkId = m_id; - nconf->timestamp = RR->node->now(); + nconf->timestamp = (cc.clock < 0) ? cc.ticks : cc.clock; nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; nconf->revision = 1; nconf->issuedTo = RR->identity.address(); @@ -1319,7 +1318,7 @@ void Network::m_requestConfiguration(void *tPtr) Utils::hex((uint16_t)endPortRange, nconf->name + 11); nconf->name[15] = (char)0; - this->setConfiguration(tPtr, *nconf, false); + this->setConfiguration(cc, *nconf, false); } else { this->setNotFound(); } @@ -1340,7 +1339,7 @@ void Network::m_requestConfiguration(void *tPtr) ScopedPtr< NetworkConfig > nconf(new NetworkConfig()); nconf->networkId = m_id; - nconf->timestamp = RR->node->now(); + nconf->timestamp = (cc.clock < 0) ? cc.ticks : cc.clock; nconf->credentialTimeMaxDelta = ZT_NETWORKCONFIG_DEFAULT_CREDENTIAL_TIME_MAX_MAX_DELTA; nconf->revision = 1; nconf->issuedTo = RR->identity.address(); @@ -1377,7 +1376,7 @@ void Network::m_requestConfiguration(void *tPtr) nconf->name[nn++] = '0'; nconf->name[nn] = (char)0; - this->setConfiguration(tPtr, *nconf, false); + this->setConfiguration(cc, *nconf, false); } return; } @@ -1397,7 +1396,7 @@ void Network::m_requestConfiguration(void *tPtr) rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_FLAGS, (uint64_t)0); rmd.add(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_RULES_ENGINE_REV, (uint64_t)ZT_RULES_ENGINE_REVISION); - RR->t->networkConfigRequestSent(tPtr, 0x335bb1a2, m_id); + RR->t->networkConfigRequestSent(cc, 0x335bb1a2, m_id); if (ctrl == RR->identity.address()) { if (RR->localNetworkController) { diff --git a/core/Network.hpp b/core/Network.hpp index 51db795d9..af7bf2492 100644 --- a/core/Network.hpp +++ b/core/Network.hpp @@ -26,6 +26,7 @@ #include "NetworkConfig.hpp" #include "MembershipCredential.hpp" #include "Containers.hpp" +#include "CallContext.hpp" #define ZT_NETWORK_MAX_INCOMING_UPDATES 3 @@ -60,14 +61,18 @@ public: * Note that init() should be called immediately after the network is * constructed to actually configure the port. * - * @param renv Runtime environment - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param nwid Network ID * @param controllerFingerprint Initial controller fingerprint if non-NULL * @param uptr Arbitrary pointer used by externally-facing API (for user use) * @param nconf Network config, if known */ - Network(const RuntimeEnvironment *renv, void *tPtr, uint64_t nwid, const Fingerprint &controllerFingerprint, void *uptr, const NetworkConfig *nconf); + Network( + const RuntimeEnvironment *renv, + CallContext &cc, + uint64_t nwid, + const Fingerprint &controllerFingerprint, + void *uptr, + const NetworkConfig *nconf); ~Network(); @@ -103,7 +108,6 @@ public: * such as TEE may be taken, and credentials may be pushed, so this is not * side-effect-free. It's basically step one in sending something over VL2. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param noTee If true, do not TEE anything anywhere (for two-pass filtering as done with multicast and bridging) * @param ztSource Source ZeroTier address * @param ztDest Destination ZeroTier address @@ -116,7 +120,7 @@ public: * @return True if packet should be sent, false if dropped or redirected */ bool filterOutgoingPacket( - void *tPtr, + CallContext &cc, bool noTee, const Address &ztSource, const Address &ztDest, @@ -136,7 +140,6 @@ public: * a match certain actions may be taken such as sending a copy of the packet * to a TEE or REDIRECT target. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param sourcePeer Source Peer * @param ztDest Destination ZeroTier address * @param macSource Ethernet layer source address @@ -148,7 +151,7 @@ public: * @return 0 == drop, 1 == accept, 2 == accept even if bridged */ int filterIncomingPacket( - void *tPtr, + CallContext &cc, const SharedPtr< Peer > &sourcePeer, const Address &ztDest, const MAC &macSource, @@ -158,30 +161,12 @@ public: unsigned int etherType, unsigned int vlanId); - /** - * Check whether we are subscribed to a multicast group - * - * @param mg Multicast group - * @param includeBridgedGroups If true, also check groups we've learned via bridging - * @return True if this network endpoint / peer is a member - */ - ZT_INLINE bool subscribedToMulticastGroup(const MulticastGroup &mg, const bool includeBridgedGroups) const - { - Mutex::Lock l(m_myMulticastGroups_l); - if (std::binary_search(m_myMulticastGroups.begin(), m_myMulticastGroups.end(), mg)) - return true; - else if (includeBridgedGroups) - return (m_multicastGroupsBehindMe.find(mg) != m_multicastGroupsBehindMe.end()); - return false; - } - /** * Subscribe to a multicast group * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param mg New multicast group */ - void multicastSubscribe(void *tPtr, const MulticastGroup &mg); + void multicastSubscribe(CallContext &cc, const MulticastGroup &mg); /** * Unsubscribe from a multicast group @@ -198,7 +183,6 @@ public: * bit of packet parsing code that also verifies chunks and replicates * them (via rumor mill flooding) if their fast propagate flag is set. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param packetId Packet ID or 0 if none (e.g. via cluster path) * @param source Peer that actually sent this chunk (probably controller) * @param chunk Buffer containing chunk @@ -206,7 +190,13 @@ public: * @param size Size of data in chunk buffer (total, not relative to ptr) * @return Update ID if update was fully assembled and accepted or 0 otherwise */ - uint64_t handleConfigChunk(void *tPtr, uint64_t packetId, const SharedPtr< Peer > &source, const Buf &chunk, int ptr, int size); + uint64_t handleConfigChunk( + CallContext &cc, + uint64_t packetId, + const SharedPtr< Peer > &source, + const Buf &chunk, + int ptr, + int size); /** * Set network configuration @@ -215,12 +205,14 @@ public: * and fully assembled, but it can also be called on Node startup when * cached configurations are re-read from the data store. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param nconf Network configuration * @param saveToDisk Save to disk? Used during loading, should usually be true otherwise. * @return 0 == bad, 1 == accepted but duplicate/unchanged, 2 == accepted and new */ - int setConfiguration(void *tPtr, const NetworkConfig &nconf, bool saveToDisk); + int setConfiguration( + CallContext &cc, + const NetworkConfig &nconf, + bool saveToDisk); /** * Set netconf failure to 'access denied' -- called in IncomingPacket when controller reports this @@ -245,7 +237,7 @@ public: /** * Do periodic cleanup and housekeeping tasks */ - void doPeriodicTasks(void *tPtr, int64_t now); + void doPeriodicTasks(CallContext &cc); /** * Find the node on this network that has this MAC behind it (if any) @@ -275,7 +267,7 @@ public: * @param mg Multicast group * @param now Current time */ - ZT_INLINE void learnBridgedMulticastGroup(void *tPtr, const MulticastGroup &mg, int64_t now) + ZT_INLINE void learnBridgedMulticastGroup(const MulticastGroup &mg, int64_t now) { Mutex::Lock l(m_myMulticastGroups_l); m_multicastGroupsBehindMe[mg] = now; @@ -284,36 +276,34 @@ public: /** * Validate a credential and learn it if it passes certificate and other checks */ - Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const MembershipCredential &com); + Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const MembershipCredential &com); /** * Validate a credential and learn it if it passes certificate and other checks */ - Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const CapabilityCredential &cap); + Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const CapabilityCredential &cap); /** * Validate a credential and learn it if it passes certificate and other checks */ - Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const TagCredential &tag); + Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const TagCredential &tag); /** * Validate a credential and learn it if it passes certificate and other checks */ - Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const RevocationCredential &rev); + Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const RevocationCredential &rev); /** * Validate a credential and learn it if it passes certificate and other checks */ - Member::AddCredentialResult addCredential(void *tPtr, const Identity &sourcePeerIdentity, const OwnershipCredential &coo); + Member::AddCredentialResult addCredential(CallContext &cc, const Identity &sourcePeerIdentity, const OwnershipCredential &coo); /** * Push credentials to a peer if timeouts indicate that we should do so * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param to Destination peer - * @param now Current time */ - void pushCredentials(void *tPtr, const SharedPtr< Peer > &to, int64_t now); + void pushCredentials(CallContext &cc, const SharedPtr< Peer > &to); /** * Destroy this network @@ -352,7 +342,7 @@ public: { return &m_uPtr; } private: - void m_requestConfiguration(void *tPtr); + void m_requestConfiguration(CallContext &cc); ZT_VirtualNetworkStatus m_status() const; diff --git a/core/NetworkController.hpp b/core/NetworkController.hpp index 7feb2928b..202fdd10d 100644 --- a/core/NetworkController.hpp +++ b/core/NetworkController.hpp @@ -54,7 +54,7 @@ public: * @param nc Network configuration to send * @param sendLegacyFormatConfig If true, send an old-format network config */ - virtual void ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig) = 0; + virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) = 0; /** * Send revocation to a node @@ -62,7 +62,7 @@ public: * @param destination Destination node address * @param rev Revocation to send */ - virtual void ncSendRevocation(const Address &destination,const RevocationCredential &rev) = 0; + virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev) = 0; /** * Send a network configuration request error @@ -72,7 +72,7 @@ public: * @param destination Destination peer Address * @param errorCode Error code */ - virtual void ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &destination,NetworkController::ErrorCode errorCode) = 0; + virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) = 0; }; NetworkController() {} @@ -84,7 +84,7 @@ public: * @param signingId Identity for signing of network configurations, certs, etc. * @param sender Sender implementation for sending replies or config pushes */ - virtual void init(const Identity &signingId,Sender *sender) = 0; + virtual void init(const Identity &signingId, Sender *sender) = 0; /** * Handle a network configuration request diff --git a/core/Node.cpp b/core/Node.cpp index 1cff6dfb7..001713b88 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -35,13 +35,13 @@ namespace { struct _NodeObjects { - ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR, Node *const n, void *const tPtr, const int64_t now) : + ZT_INLINE _NodeObjects(RuntimeEnvironment *const RR, CallContext &cc) : networks(), t(RR), expect(), vl2(RR), vl1(RR), - topology(RR, tPtr, now), + topology(RR, cc), sa(RR), ts() { @@ -69,9 +69,8 @@ struct _NodeObjects Node::Node( void *uPtr, - void *tPtr, const struct ZT_Node_Callbacks *callbacks, - int64_t now) : + CallContext &cc) : m_RR(this), RR(&m_RR), m_store(&m_RR), @@ -79,8 +78,7 @@ Node::Node( m_lastPeerPulse(0), m_lastHousekeepingRun(0), m_lastNetworkHousekeepingRun(0), - m_lastRootRank(0), - m_now(now), + m_lastTrustStoreUpdate(0), m_online(false) { ZT_SPEW("Node starting up!"); @@ -89,7 +87,7 @@ Node::Node( m_RR.uPtr = uPtr; m_RR.store = &m_store; - Vector< uint8_t > data(m_store.get(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0)); + Vector< uint8_t > data(m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0)); bool haveIdentity = false; if (!data.empty()) { data.push_back(0); // zero-terminate string @@ -105,13 +103,13 @@ Node::Node( m_RR.identity.generate(Identity::C25519); m_RR.identity.toString(false, m_RR.publicIdentityStr); m_RR.identity.toString(true, m_RR.secretIdentityStr); - m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_RR.secretIdentityStr, (unsigned int)strlen(m_RR.secretIdentityStr)); - m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); + m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_SECRET, Utils::ZERO256, 0, m_RR.secretIdentityStr, (unsigned int)strlen(m_RR.secretIdentityStr)); + m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); ZT_SPEW("no pre-existing identity found, created %s", RR->identity.toString().c_str()); } else { - data = m_store.get(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0); + data = m_store.get(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0); if ((data.empty()) || (memcmp(data.data(), m_RR.publicIdentityStr, strlen(m_RR.publicIdentityStr)) != 0)) - m_store.put(tPtr, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); + m_store.put(cc, ZT_STATE_OBJECT_IDENTITY_PUBLIC, Utils::ZERO256, 0, m_RR.publicIdentityStr, (unsigned int)strlen(m_RR.publicIdentityStr)); } uint8_t localSecretCipherKey[ZT_FINGERPRINT_HASH_SIZE]; @@ -133,10 +131,10 @@ Node::Node( } } - m_objects = new _NodeObjects(&m_RR, this, tPtr, now); + m_objects = new _NodeObjects(&m_RR, cc); ZT_SPEW("node initialized!"); - postEvent(tPtr, ZT_EVENT_UP); + postEvent(cc.tPtr, ZT_EVENT_UP); } Node::~Node() @@ -157,28 +155,59 @@ Node::~Node() Buf::freePool(); } -void Node::shutdown(void *tPtr) +void Node::shutdown(CallContext &cc) { m_allNetworks_l.lock(); RR->networks->clear(); m_allNetworks.clear(); m_allNetworks_l.unlock(); - postEvent(tPtr, ZT_EVENT_DOWN); + + postEvent(cc.tPtr, ZT_EVENT_DOWN); + if (RR->topology) - RR->topology->saveAll(tPtr); + RR->topology->saveAll(cc); } ZT_ResultCode Node::processBackgroundTasks( - void *tPtr, - int64_t now, + CallContext &cc, volatile int64_t *nextBackgroundTaskDeadline) { - m_now = now; Mutex::Lock bl(m_backgroundTasksLock); try { - if ((now - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) { - m_lastPeerPulse = now; + // Updating the trust store means checking certificates and certificate chains + // against the current time, etc., and also resynchronizing roots as specified by + // certificates. This also happens on demand when the trust store is changed. + if ((cc.ticks - m_lastTrustStoreUpdate) >= ZT_TRUSTSTORE_UPDATE_PERIOD) { + m_lastTrustStoreUpdate = cc.ticks; + if (RR->ts->update(cc.ticks, nullptr)) + RR->topology->trustStoreChanged(cc); + } + + // Networks perform housekeeping here such as refreshing configs. + if ((cc.ticks - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) { + m_lastNetworkHousekeepingRun = cc.ticks; + ZT_SPEW("running networking housekeeping..."); + Mutex::Lock l(m_allNetworks_l); + for (Vector< SharedPtr< Network > >::const_iterator n(m_allNetworks.begin()); n != m_allNetworks.end(); ++n) + (*n)->doPeriodicTasks(cc); + } + + // Perform general housekeeping for other objects in the system. + if ((cc.ticks - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { + m_lastHousekeepingRun = cc.ticks; + ZT_SPEW("running housekeeping..."); + + RR->topology->doPeriodicTasks(cc); + RR->sa->clean(cc); + } + + // Peers have a "pulse" method that does things like keepalive and path housekeeping. + // This happens last because keepalives are only necessary if nothing has been sent + // in a while, and some of the above actions may cause peers to send things which may + // reduce the need for keepalives. Root ranking also happens here. + if ((cc.ticks - m_lastPeerPulse) >= ZT_PEER_PULSE_INTERVAL) { + m_lastPeerPulse = cc.ticks; ZT_SPEW("running pulse() on each peer..."); try { Vector< SharedPtr< Peer > > allPeers, rootPeers; @@ -187,41 +216,21 @@ ZT_ResultCode Node::processBackgroundTasks( 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)); + (*p)->pulse(cc, isRoot); + online |= ((isRoot || rootPeers.empty()) && (*p)->directlyConnected(cc)); } if (m_online.exchange(online) != online) - postEvent(tPtr, online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + postEvent(cc.tPtr, online ? ZT_EVENT_ONLINE : ZT_EVENT_OFFLINE); + + ZT_SPEW("ranking roots..."); + RR->topology->rankRoots(cc); } catch (...) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } } - if ((now - m_lastNetworkHousekeepingRun) >= ZT_NETWORK_HOUSEKEEPING_PERIOD) { - m_lastHousekeepingRun = now; - ZT_SPEW("running networking housekeeping..."); - Mutex::Lock l(m_allNetworks_l); - for (Vector< SharedPtr< Network > >::const_iterator i(m_allNetworks.begin()); i != m_allNetworks.end(); ++i) { - (*i)->doPeriodicTasks(tPtr, now); - } - } - - if ((now - m_lastHousekeepingRun) >= ZT_HOUSEKEEPING_PERIOD) { - m_lastHousekeepingRun = now; - ZT_SPEW("running housekeeping..."); - - RR->topology->doPeriodicTasks(tPtr, now); - RR->sa->clean(now); - } - - if ((now - m_lastRootRank) >= ZT_ROOT_RANK_PERIOD) { - m_lastRootRank = now; - ZT_SPEW("ranking roots..."); - RR->topology->rankRoots(now); - } - - *nextBackgroundTaskDeadline = now + ZT_TIMER_TASK_INTERVAL; + *nextBackgroundTaskDeadline = cc.ticks + ZT_TIMER_TASK_INTERVAL; } catch (...) { return ZT_RESULT_FATAL_ERROR_INTERNAL; } @@ -233,7 +242,7 @@ ZT_ResultCode Node::join( uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, - void *tptr) + CallContext &cc) { Mutex::Lock l(m_allNetworks_l); @@ -249,7 +258,7 @@ ZT_ResultCode Node::join( if ((*n)->id() == nwid) return ZT_RESULT_OK; } - SharedPtr< Network > network(new Network(RR, tptr, nwid, fp, uptr, nullptr)); + SharedPtr< Network > network(new Network(RR, cc, nwid, fp, uptr, nullptr)); m_allNetworks.push_back(network); RR->networks->set(nwid, network); @@ -259,7 +268,7 @@ ZT_ResultCode Node::join( ZT_ResultCode Node::leave( uint64_t nwid, void **uptr, - void *tptr) + CallContext &cc) { Mutex::Lock l(m_allNetworks_l); @@ -279,21 +288,22 @@ ZT_ResultCode Node::leave( uint64_t tmp[2]; tmp[0] = nwid; tmp[1] = 0; - m_store.erase(tptr, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1); + m_store.erase(cc, ZT_STATE_OBJECT_NETWORK_CONFIG, tmp, 1); if (network) { if (uptr) *uptr = *network->userPtr(); network->externalConfig(&ctmp); - RR->node->configureVirtualNetworkPort(tptr, nwid, uptr, ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp); + RR->cb.virtualNetworkConfigFunction(reinterpret_cast(this), RR->uPtr, cc.tPtr, nwid, network->userPtr(), ZT_VIRTUAL_NETWORK_CONFIG_OPERATION_DESTROY, &ctmp); network->destroy(); return ZT_RESULT_OK; + } else { + return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } - return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; } ZT_ResultCode Node::multicastSubscribe( - void *tPtr, + CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) @@ -301,7 +311,7 @@ ZT_ResultCode Node::multicastSubscribe( ZT_SPEW("multicast subscribe to %s:%lu", MAC(multicastGroup).toString().c_str(), multicastAdi); const SharedPtr< Network > nw(RR->networks->get(nwid)); if (nw) { - nw->multicastSubscribe(tPtr, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff))); + nw->multicastSubscribe(cc, MulticastGroup(MAC(multicastGroup), (uint32_t)(multicastAdi & 0xffffffff))); return ZT_RESULT_OK; } else { return ZT_RESULT_ERROR_NETWORK_NOT_FOUND; @@ -309,6 +319,7 @@ ZT_ResultCode Node::multicastSubscribe( } ZT_ResultCode Node::multicastUnsubscribe( + CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi) @@ -353,7 +364,7 @@ struct p_sortPeerPtrsByAddress { return (a->address() < b->address()); } }; -ZT_PeerList *Node::peers() const +ZT_PeerList *Node::peers(CallContext &cc) const { p_ZT_PeerListPrivate *pl = nullptr; try { @@ -364,7 +375,6 @@ ZT_PeerList *Node::peers() const RR->topology->allPeers(peers, rootPeers); std::sort(peers.begin(), peers.end(), p_sortPeerPtrsByAddress()); std::sort(rootPeers.begin(), rootPeers.end()); - int64_t now = m_now; for (Vector< SharedPtr< Peer > >::iterator pi(peers.begin()); pi != peers.end(); ++pi) { pl->p_peers.push_back(ZT_Peer()); @@ -405,7 +415,7 @@ ZT_PeerList *Node::peers() const Utils::copy< sizeof(struct sockaddr_storage) >(&(apip.endpoint.value.ss), &(ztp->address().as.ss)); apip.lastSend = ztp->lastOut(); apip.lastReceive = ztp->lastIn(); - apip.alive = ztp->alive(now) ? 1 : 0; + apip.alive = ztp->alive(cc) ? 1 : 0; apip.preferred = (i == 0) ? 1 : 0; } p.paths = apiPaths.data(); @@ -499,40 +509,8 @@ void Node::setInterfaceAddresses( } } -ZT_ResultCode Node::addPeer( - void *tptr, - const ZT_Identity *identity) -{ - if (!identity) - return ZT_RESULT_ERROR_BAD_PARAMETER; - SharedPtr< Peer > peer(RR->topology->peer(tptr, reinterpret_cast(identity)->address())); - if (!peer) { - peer.set(new Peer(RR)); - peer->init(*reinterpret_cast(identity)); - peer = RR->topology->add(tptr, peer); - } - return (peer->identity() == *reinterpret_cast(identity)) ? ZT_RESULT_OK : ZT_RESULT_ERROR_COLLIDING_OBJECT; -} - -int Node::tryPeer( - void *tptr, - const ZT_Fingerprint *fp, - const ZT_Endpoint *endpoint, - int retries) -{ - if ((!fp) || (!endpoint)) - return 0; - const SharedPtr< Peer > peer(RR->topology->peer(tptr, fp->address, true)); - if ((peer) && (peer->identity().fingerprint().bestSpecificityEquals(*fp))) { - peer->contact(tptr, m_now, Endpoint(*endpoint), std::min(retries, 1)); - return 1; - } - return 0; -} - ZT_CertificateError Node::addCertificate( - void *tptr, - int64_t now, + CallContext &cc, unsigned int localTrust, const ZT_Certificate *cert, const void *certData, @@ -548,13 +526,13 @@ ZT_CertificateError Node::addCertificate( return ZT_CERTIFICATE_ERROR_INVALID_FORMAT; } RR->ts->add(c, localTrust); - RR->ts->update(now, nullptr); + RR->ts->update(cc.clock, nullptr); SharedPtr< TrustStore::Entry > ent(RR->ts->get(c.getSerialNo())); return (ent) ? ent->error() : ZT_CERTIFICATE_ERROR_INVALID_FORMAT; // should never be null, but if so it means invalid } ZT_ResultCode Node::deleteCertificate( - void *tptr, + CallContext &cc, const void *serialNo) { if (!serialNo) @@ -605,11 +583,11 @@ ZT_CertificateList *Node::listCertificates() } int Node::sendUserMessage( - void *tptr, + CallContext &cc, uint64_t dest, - uint64_t typeId, - const void *data, - unsigned int len) + uint64_t /*typeId*/, + const void */*data*/, + unsigned int /*len*/) { try { if (RR->identity.address().toInt() != dest) { @@ -679,13 +657,14 @@ bool Node::externalPathLookup(void *tPtr, const Identity &id, int family, InetAd // Implementation of NetworkController::Sender ------------------------------------------------------------------------ -void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) +void Node::ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig) { if (destination == RR->identity.address()) { SharedPtr< Network > n(RR->networks->get(nwid)); if (!n) return; - n->setConfiguration((void *)0, nc, true); + CallContext cc(clock, ticks, tPtr); + n->setConfiguration(cc, nc, true); } else { Dictionary dconf; if (nc.toDictionary(dconf)) { @@ -731,13 +710,14 @@ void Node::ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address & } } -void Node::ncSendRevocation(const Address &destination, const RevocationCredential &rev) +void Node::ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev) { if (destination == RR->identity.address()) { SharedPtr< Network > n(RR->networks->get(rev.networkId())); if (!n) return; - n->addCredential(nullptr, RR->identity, rev); + CallContext cc(clock, ticks, tPtr); + n->addCredential(cc, RR->identity, rev); } else { // TODO /* @@ -753,7 +733,7 @@ void Node::ncSendRevocation(const Address &destination, const RevocationCredenti } } -void Node::ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) +void Node::ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode) { if (destination == RR->identity.address()) { SharedPtr< Network > n(RR->networks->get(nwid)); diff --git a/core/Node.hpp b/core/Node.hpp index 828cec94c..209dd9788 100644 --- a/core/Node.hpp +++ b/core/Node.hpp @@ -26,6 +26,7 @@ #include "Buf.hpp" #include "Containers.hpp" #include "Store.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -43,37 +44,35 @@ public: void operator delete(void* p) { _mm_free(p); } #endif - Node(void *uPtr, void *tPtr, const struct ZT_Node_Callbacks *callbacks, int64_t now); + Node(void *uPtr, const struct ZT_Node_Callbacks *callbacks, CallContext &cc); virtual ~Node(); - void shutdown(void *tPtr); - - // Public API Functions --------------------------------------------------------------------------------------------- + void shutdown(CallContext &cc); ZT_ResultCode processBackgroundTasks( - void *tPtr, - int64_t now, + CallContext &cc, volatile int64_t *nextBackgroundTaskDeadline); ZT_ResultCode join( uint64_t nwid, const ZT_Fingerprint *controllerFingerprint, void *uptr, - void *tptr); + CallContext &cc); ZT_ResultCode leave( uint64_t nwid, void **uptr, - void *tptr); + CallContext &cc); ZT_ResultCode multicastSubscribe( - void *tPtr, + CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi); ZT_ResultCode multicastUnsubscribe( + CallContext &cc, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi); @@ -81,7 +80,8 @@ public: void status( ZT_NodeStatus *status) const; - ZT_PeerList *peers() const; + ZT_PeerList *peers( + CallContext &cc) const; ZT_VirtualNetworkConfig *networkConfig( uint64_t nwid) const; @@ -96,32 +96,21 @@ public: const ZT_InterfaceAddress *addrs, unsigned int addrCount); - ZT_ResultCode addPeer( - void *tptr, - const ZT_Identity *identity); - - int tryPeer( - void *tptr, - const ZT_Fingerprint *fp, - const ZT_Endpoint *endpoint, - int retries); - ZT_CertificateError addCertificate( - void *tptr, - int64_t now, + CallContext &cc, unsigned int localTrust, const ZT_Certificate *cert, const void *certData, unsigned int certSize); ZT_ResultCode deleteCertificate( - void *tptr, + CallContext &cc, const void *serialNo); ZT_CertificateList *listCertificates(); int sendUserMessage( - void *tptr, + CallContext &cc, uint64_t dest, uint64_t typeId, const void *data, @@ -130,23 +119,6 @@ public: void setController( void *networkControllerInstance); - // Internal functions ----------------------------------------------------------------------------------------------- - - /** - * @return Most recent time value supplied to core via API - */ - ZT_INLINE int64_t now() const noexcept - { return m_now; } - - /** - * @return Known local interface addresses for this node - */ - ZT_INLINE Vector< ZT_InterfaceAddress > localInterfaceAddresses() const - { - Mutex::Lock _l(m_localInterfaceAddresses_m); - return m_localInterfaceAddresses; - } - /** * Post an event via external callback * @@ -158,18 +130,6 @@ public: ZT_INLINE void postEvent(void *tPtr, ZT_Event ev, const void *md = nullptr, const unsigned int mdSize = 0) noexcept { RR->cb.eventCallback(reinterpret_cast(this), RR->uPtr, tPtr, ev, md, mdSize); } - /** - * Post network port configuration via external callback - * - * @param tPtr Thread pointer - * @param nwid Network ID - * @param nuptr Network-associated user pointer - * @param op Config operation or event type - * @param nc Network config info - */ - ZT_INLINE void configureVirtualNetworkPort(void *tPtr, uint64_t nwid, void **nuptr, ZT_VirtualNetworkConfigOperation op, const ZT_VirtualNetworkConfig *nc) noexcept - { RR->cb.virtualNetworkConfigFunction(reinterpret_cast(this), RR->uPtr, tPtr, nwid, nuptr, op, nc); } - /** * Check whether a path should be used for ZeroTier traffic * @@ -201,9 +161,9 @@ public: { return m_RR.identity; } // Implementation of NetworkController::Sender interface - virtual void ncSendConfig(uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig); - virtual void ncSendRevocation(const Address &destination, const RevocationCredential &rev); - virtual void ncSendError(uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode); + virtual void ncSendConfig(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, const NetworkConfig &nc, bool sendLegacyFormatConfig); + virtual void ncSendRevocation(void *tPtr, int64_t clock, int64_t ticks, const Address &destination, const RevocationCredential &rev); + virtual void ncSendError(void *tPtr, int64_t clock, int64_t ticks, uint64_t nwid, uint64_t requestPacketId, const Address &destination, NetworkController::ErrorCode errorCode); private: RuntimeEnvironment m_RR; @@ -234,10 +194,7 @@ private: int64_t m_lastPeerPulse; int64_t m_lastHousekeepingRun; int64_t m_lastNetworkHousekeepingRun; - int64_t m_lastRootRank; - - // This is the most recent value for time passed in via any of the core API methods. - std::atomic< int64_t > m_now; + int64_t m_lastTrustStoreUpdate; // True if at least one root appears reachable. std::atomic< bool > m_online; diff --git a/core/OS.hpp b/core/OS.hpp index 64c6b6ae8..3d0f6b376 100644 --- a/core/OS.hpp +++ b/core/OS.hpp @@ -161,11 +161,22 @@ #endif #ifdef __cplusplus -#if __cplusplus > 199711L +#if __cplusplus >= 199711L + #include #ifndef __CPP11__ #define __CPP11__ 1 #endif + +#if __cplusplus >= 201703L +#define ZT_MAYBE_UNUSED [[maybe_unused]] +#ifndef __CPP17__ +#define __CPP17__ 1 +#endif +#else +#define ZT_MAYBE_UNUSED +#endif + #endif #if defined(ZT_ARCH_X64) || defined(__aarch64__) diff --git a/core/OwnershipCredential.cpp b/core/OwnershipCredential.cpp index 1f1098711..4fb0f7a80 100644 --- a/core/OwnershipCredential.cpp +++ b/core/OwnershipCredential.cpp @@ -19,11 +19,11 @@ void OwnershipCredential::addThing(const InetAddress &ip) { if (m_thingCount >= ZT_CERTIFICATEOFOWNERSHIP_MAX_THINGS) return; - if (ip.family() == AF_INET) { + if (ip.as.sa.sa_family == AF_INET) { m_thingTypes[m_thingCount] = THING_IPV4_ADDRESS; Utils::copy<4>(m_thingValues[m_thingCount], &(reinterpret_cast(&ip)->sin_addr.s_addr)); ++m_thingCount; - } else if (ip.family() == AF_INET6) { + } else if (ip.as.sa.sa_family == AF_INET6) { m_thingTypes[m_thingCount] = THING_IPV6_ADDRESS; Utils::copy<16>(m_thingValues[m_thingCount], reinterpret_cast(&ip)->sin6_addr.s6_addr); ++m_thingCount; diff --git a/core/OwnershipCredential.hpp b/core/OwnershipCredential.hpp index e9a7d7bfd..96b383486 100644 --- a/core/OwnershipCredential.hpp +++ b/core/OwnershipCredential.hpp @@ -45,7 +45,8 @@ class OwnershipCredential : public Credential friend class Credential; public: - static constexpr ZT_CredentialType credentialType() noexcept { return ZT_CREDENTIAL_TYPE_COO; } + static constexpr ZT_CredentialType credentialType() noexcept + { return ZT_CREDENTIAL_TYPE_COO; } enum Thing { @@ -55,7 +56,8 @@ public: THING_IPV6_ADDRESS = 3 }; - ZT_INLINE OwnershipCredential() noexcept { memoryZero(this); } + ZT_INLINE OwnershipCredential() noexcept + { memoryZero(this); } ZT_INLINE OwnershipCredential(const uint64_t nwid, const int64_t ts, const Address &issuedTo, const uint32_t id) noexcept { @@ -66,32 +68,53 @@ public: m_issuedTo = issuedTo; } - ZT_INLINE uint64_t networkId() const noexcept { return m_networkId; } - ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } - ZT_INLINE uint32_t id() const noexcept { return m_id; } - ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } - ZT_INLINE const Address &signer() const noexcept { return m_signedBy; } - ZT_INLINE const uint8_t *signature() const noexcept { return m_signature; } - ZT_INLINE unsigned int signatureLength() const noexcept { return m_signatureLength; } + ZT_INLINE uint64_t networkId() const noexcept + { return m_networkId; } - ZT_INLINE unsigned int thingCount() const noexcept { return (unsigned int)m_thingCount; } - ZT_INLINE Thing thingType(const unsigned int i) const noexcept { return (Thing)m_thingTypes[i]; } - ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept { return m_thingValues[i]; } + ZT_INLINE int64_t timestamp() const noexcept + { return m_ts; } + + ZT_INLINE int64_t revision() const noexcept + { return m_ts; } + + ZT_INLINE uint32_t id() const noexcept + { return m_id; } + + ZT_INLINE const Address &issuedTo() const noexcept + { return m_issuedTo; } + + ZT_INLINE const Address &signer() const noexcept + { return m_signedBy; } + + ZT_INLINE const uint8_t *signature() const noexcept + { return m_signature; } + + ZT_INLINE unsigned int signatureLength() const noexcept + { return m_signatureLength; } + + ZT_INLINE unsigned int thingCount() const noexcept + { return (unsigned int)m_thingCount; } + + ZT_INLINE Thing thingType(const unsigned int i) const noexcept + { return (Thing)m_thingTypes[i]; } + + ZT_INLINE const uint8_t *thingValue(const unsigned int i) const noexcept + { return m_thingValues[i]; } ZT_INLINE bool owns(const InetAddress &ip) const noexcept { - if (ip.family() == AF_INET) - return this->_owns(THING_IPV4_ADDRESS,&(reinterpret_cast(&ip)->sin_addr.s_addr),4); - if (ip.family() == AF_INET6) - return this->_owns(THING_IPV6_ADDRESS,reinterpret_cast(&ip)->sin6_addr.s6_addr,16); - return false; + if (ip.as.sa.sa_family == AF_INET) + return this->_owns(THING_IPV4_ADDRESS, &(reinterpret_cast(&ip)->sin_addr.s_addr), 4); + else if (ip.as.sa.sa_family == AF_INET6) + return this->_owns(THING_IPV6_ADDRESS, reinterpret_cast(&ip)->sin6_addr.s6_addr, 16); + else return false; } ZT_INLINE bool owns(const MAC &mac) const noexcept { uint8_t tmp[6]; mac.copyTo(tmp); - return this->_owns(THING_MAC_ADDRESS,tmp,6); + return this->_owns(THING_MAC_ADDRESS, tmp, 6); } /** @@ -127,22 +150,30 @@ public: * @param tPtr That pointer we pass around * @return Credential verification result: OK, bad signature, or identity needed */ - ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR,void *tPtr) const { return s_verify(RR, tPtr, *this); } + ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const + { return s_verify(RR, cc, *this); } - static constexpr int marshalSizeMax() noexcept { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; } - int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign = false) const noexcept; - int unmarshal(const uint8_t *data,int len) noexcept; + static constexpr int marshalSizeMax() noexcept + { return ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX; } + + int marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign = false) const noexcept; + + int unmarshal(const uint8_t *data, int len) noexcept; // Provides natural sort order by ID - ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept { return (m_id < coo.m_id); } + ZT_INLINE bool operator<(const OwnershipCredential &coo) const noexcept + { return (m_id < coo.m_id); } - ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); } - ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept { return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); } + ZT_INLINE bool operator==(const OwnershipCredential &coo) const noexcept + { return (memcmp(this, &coo, sizeof(OwnershipCredential)) == 0); } + + ZT_INLINE bool operator!=(const OwnershipCredential &coo) const noexcept + { return (memcmp(this, &coo, sizeof(OwnershipCredential)) != 0); } private: - ZT_INLINE bool _owns(const Thing &t,const void *v,unsigned int l) const noexcept + ZT_INLINE bool _owns(const Thing &t, const void *v, unsigned int l) const noexcept { - for(unsigned int i=0,j=m_thingCount;i < j;++i) { + for (unsigned int i = 0, j = m_thingCount; i < j; ++i) { if (m_thingTypes[i] == (uint8_t)t) { unsigned int k = 0; while (k < l) { diff --git a/core/Path.cpp b/core/Path.cpp index a47ae5bee..49b21ab5a 100644 --- a/core/Path.cpp +++ b/core/Path.cpp @@ -17,11 +17,11 @@ namespace ZeroTier { -bool Path::send(const RuntimeEnvironment *const RR, void *const tPtr, const void *const data, const unsigned int len, const int64_t now) noexcept +bool Path::send(const RuntimeEnvironment *const RR, CallContext &cc, const void *const data, const unsigned int len) noexcept { - if (likely(RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, m_localSocket, reinterpret_cast(&m_addr), data, len, 0) == 0)) { - m_lastOut = now; - m_outMeter.log(now, len); + if (likely(RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, m_localSocket, reinterpret_cast(&m_addr), data, len, 0) == 0)) { + m_lastOut = cc.ticks; + m_outMeter.log(cc.ticks, len); return true; } return false; diff --git a/core/Path.hpp b/core/Path.hpp index 4b3d55652..f7396a42c 100644 --- a/core/Path.hpp +++ b/core/Path.hpp @@ -21,6 +21,7 @@ #include "Mutex.hpp" #include "Meter.hpp" #include "Containers.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -140,14 +141,11 @@ public: /** * Send a packet via this path (last out time is also updated) * - * @param RR Runtime environment - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param data Packet data * @param len Packet length - * @param now Current time * @return True if transport reported success */ - bool send(const RuntimeEnvironment *RR, void *tPtr, const void *data, unsigned int len, int64_t now) noexcept; + bool send(const RuntimeEnvironment *RR, CallContext &cc, const void *data, unsigned int len) noexcept; /** * Explicitly update last sent time @@ -155,10 +153,10 @@ public: * @param now Time of send * @param bytes Bytes sent */ - ZT_INLINE void sent(const int64_t now, const unsigned int bytes) noexcept + ZT_INLINE void sent(const CallContext &cc, const unsigned int bytes) noexcept { - m_lastOut.store(now); - m_outMeter.log(now, bytes); + m_lastOut.store(cc.ticks, std::memory_order_relaxed); + m_outMeter.log(cc.ticks, bytes); } /** @@ -167,10 +165,10 @@ public: * @param now Time of receive * @param bytes Bytes received */ - ZT_INLINE void received(const int64_t now, const unsigned int bytes) noexcept + ZT_INLINE void received(const CallContext &cc, const unsigned int bytes) noexcept { - m_lastIn.store(now); - m_inMeter.log(now, bytes); + m_lastIn.store(cc.ticks, std::memory_order_relaxed); + m_inMeter.log(cc.ticks, bytes); } /** @@ -199,8 +197,8 @@ public: * * @param now Current time */ - ZT_INLINE bool alive(const int64_t now) const noexcept - { return ((now - m_lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); } + ZT_INLINE bool alive(const CallContext &cc) const noexcept + { return ((cc.ticks - m_lastIn.load()) < ZT_PATH_ALIVE_TIMEOUT); } /** * @return Physical address diff --git a/core/Peer.cpp b/core/Peer.cpp index b7298253c..951573560 100644 --- a/core/Peer.cpp +++ b/core/Peer.cpp @@ -45,7 +45,7 @@ Peer::Peer(const RuntimeEnvironment *renv) : Peer::~Peer() { Utils::burn(m_helloMacKey, sizeof(m_helloMacKey)); } -bool Peer::init(const Identity &peerIdentity) +bool Peer::init(CallContext &cc, const Identity &peerIdentity) { RWMutex::Lock l(m_lock); @@ -56,7 +56,7 @@ bool Peer::init(const Identity &peerIdentity) uint8_t k[ZT_SYMMETRIC_KEY_SIZE]; if (!RR->identity.agree(peerIdentity, k)) return false; - m_identityKey.set(new SymmetricKey(RR->node->now(), k)); + m_identityKey.set(new SymmetricKey(cc.ticks, k)); Utils::burn(k, sizeof(k)); m_deriveSecondaryIdentityKeys(); @@ -65,7 +65,7 @@ bool Peer::init(const Identity &peerIdentity) } void Peer::received( - void *tPtr, + CallContext &cc, const SharedPtr< Path > &path, const unsigned int hops, const uint64_t packetId, @@ -73,10 +73,8 @@ void Peer::received( const Protocol::Verb verb, const Protocol::Verb inReVerb) { - const int64_t now = RR->node->now(); - - m_lastReceive = now; - m_inMeter.log(now, payloadLength); + m_lastReceive = cc.ticks; + m_inMeter.log(cc.ticks, payloadLength); if (hops == 0) { RWMutex::RMaybeWLock l(m_lock); @@ -89,7 +87,7 @@ void Peer::received( } // If we made it here, we don't already know this path. - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, path->localSocket(), path->address())) { + if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, path->localSocket(), path->address())) { // SECURITY: note that if we've made it here we expected this OK, see Expect.hpp. // There is replay protection in effect for OK responses. if (verb == Protocol::VERB_OK) { @@ -101,7 +99,7 @@ void Peer::received( if (m_alivePathCount == ZT_MAX_PEER_NETWORK_PATHS) { int64_t lastReceiveTimeMax = 0; for (unsigned int i = 0; i < m_alivePathCount; ++i) { - if ((m_paths[i]->address().family() == path->address().family()) && + if ((m_paths[i]->address().as.sa.sa_family == path->address().as.sa.sa_family) && (m_paths[i]->localSocket() == path->localSocket()) && // TODO: should be localInterface when multipath is integrated (m_paths[i]->address().ipsEqual2(path->address()))) { // Replace older path if everything is the same except the port number, since NAT/firewall reboots @@ -123,7 +121,7 @@ void Peer::received( m_paths[newPathIdx] = path; // Re-prioritize paths to include the new one. - m_prioritizePaths(now); + m_prioritizePaths(cc); // Add or update entry in the endpoint cache. If this endpoint // is already present, its timesSeen count is incremented. Otherwise @@ -133,35 +131,35 @@ void Peer::received( for (unsigned int i = 0;; ++i) { if (i == (ZT_PEER_ENDPOINT_CACHE_SIZE - 1)) { m_endpointCache[i].target = thisEndpoint; - m_endpointCache[i].lastSeen = now; + m_endpointCache[i].lastSeen = cc.ticks; break; } else if (m_endpointCache[i].target == thisEndpoint) { - m_endpointCache[i].lastSeen = now; + m_endpointCache[i].lastSeen = cc.ticks; break; } } - RR->t->learnedNewPath(tPtr, 0x582fabdd, packetId, m_id, path->address(), old); + RR->t->learnedNewPath(cc, 0x582fabdd, packetId, m_id, path->address(), old); } else { - path->sent(now, hello(tPtr, path->localSocket(), path->address(), now)); - RR->t->tryingNewPath(tPtr, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id); + path->sent(cc, hello(cc, path->localSocket(), path->address())); + RR->t->tryingNewPath(cc, 0xb7747ddd, m_id, path->address(), path->address(), packetId, (uint8_t)verb, m_id); } } } } -void Peer::send(void *tPtr, int64_t now, const void *data, unsigned int len) noexcept +void Peer::send(CallContext &cc, const void *data, unsigned int len) noexcept { - SharedPtr< Path > via(this->path(now)); + SharedPtr< Path > via(this->path(cc)); if (via) { - via->send(RR, tPtr, data, len, now); + via->send(RR, cc, data, len); } else { const SharedPtr< Peer > root(RR->topology->root()); if ((root) && (root.ptr() != this)) { - via = root->path(now); + via = root->path(cc); if (via) { - via->send(RR, tPtr, data, len, now); - root->relayed(now, len); + via->send(RR, cc, data, len); + root->relayed(cc, len); } else { return; } @@ -169,10 +167,10 @@ void Peer::send(void *tPtr, int64_t now, const void *data, unsigned int len) noe return; } } - sent(now, len); + sent(cc, len); } -unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const int64_t now) +unsigned int Peer::hello(CallContext &cc, int64_t localSocket, const InetAddress &atAddress) { Buf outp; @@ -183,7 +181,7 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA outp.wI8(ii, ZEROTIER_VERSION_MAJOR); outp.wI8(ii, ZEROTIER_VERSION_MINOR); outp.wI16(ii, ZEROTIER_VERSION_REVISION); - outp.wI64(ii, (uint64_t)now); + outp.wI64(ii, (uint64_t)cc.clock); outp.wO(ii, RR->identity); outp.wO(ii, atAddress); @@ -226,10 +224,10 @@ unsigned int Peer::hello(void *tPtr, int64_t localSocket, const InetAddress &atA p1305.finish(polyMac); Utils::storeMachineEndian< uint64_t >(outp.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, polyMac[0]); - return (likely(RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, localSocket, reinterpret_cast(&atAddress), outp.unsafeData, ii, 0) == 0)) ? ii : 0; + return (likely(RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, localSocket, reinterpret_cast(&atAddress), outp.unsafeData, ii, 0) == 0)) ? ii : 0; } -void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) +void Peer::pulse(CallContext &cc, const bool isRoot) { RWMutex::Lock l(m_lock); @@ -237,15 +235,15 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) // to be sent. The latter happens every ZT_PEER_HELLO_INTERVAL or if a new // ephemeral key pair is generated. bool needHello = false; - if ((m_vProto >= 11) && (((now - m_ephemeralPairTimestamp) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || ((m_ephemeralKeys[0]) && (m_ephemeralKeys[0]->odometer() >= (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))) { + if ((m_vProto >= 11) && (((cc.ticks - m_ephemeralPairTimestamp) >= (ZT_SYMMETRIC_KEY_TTL / 2)) || ((m_ephemeralKeys[0]) && (m_ephemeralKeys[0]->odometer() >= (ZT_SYMMETRIC_KEY_TTL_MESSAGES / 2))))) { m_ephemeralPair.generate(); needHello = true; - } else if ((now - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL) { + } else if ((cc.ticks - m_lastSentHello) >= ZT_PEER_HELLO_INTERVAL) { needHello = true; } // Prioritize paths and more importantly for here forget dead ones. - m_prioritizePaths(now); + m_prioritizePaths(cc); if (m_tryQueue.empty()) { if (m_alivePathCount == 0) { @@ -256,12 +254,12 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) if (m_locator) { for (Vector< std::pair > >::const_iterator ep(m_locator->endpoints().begin()); ep != m_locator->endpoints().end(); ++ep) { if (ep->first.type == ZT_ENDPOINT_TYPE_IP_UDP) { - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, ep->first.ip())) { + if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, ep->first.ip())) { int64_t < = m_lastTried[ep->first]; - if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { - lt = now; - RR->t->tryingNewPath(tPtr, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL); - sent(now, m_sendProbe(tPtr, -1, ep->first.ip(), nullptr, 0, now)); + if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) { + lt = cc.ticks; + RR->t->tryingNewPath(cc, 0x84b22322, m_id, ep->first.ip(), InetAddress::NIL, 0, 0, Identity::NIL); + sent(cc, m_sendProbe(cc, -1, ep->first.ip(), nullptr, 0)); } } } @@ -270,25 +268,25 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) for (unsigned int i = 0; i < ZT_PEER_ENDPOINT_CACHE_SIZE; ++i) { if ((m_endpointCache[i].lastSeen > 0) && (m_endpointCache[i].target.type == ZT_ENDPOINT_TYPE_IP_UDP)) { - if (RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, m_endpointCache[i].target.ip())) { + if (RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, m_endpointCache[i].target.ip())) { int64_t < = m_lastTried[m_endpointCache[i].target]; - if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { - lt = now; - RR->t->tryingNewPath(tPtr, 0x84b22343, m_id, m_endpointCache[i].target.ip(), InetAddress::NIL, 0, 0, Identity::NIL); - sent(now, m_sendProbe(tPtr, -1, m_endpointCache[i].target.ip(), nullptr, 0, now)); + if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) { + lt = cc.ticks; + RR->t->tryingNewPath(cc, 0x84b22343, m_id, m_endpointCache[i].target.ip(), InetAddress::NIL, 0, 0, Identity::NIL); + sent(cc, m_sendProbe(cc, -1, m_endpointCache[i].target.ip(), nullptr, 0)); } } } } InetAddress addr; - if (RR->node->externalPathLookup(tPtr, m_id, -1, addr)) { - if ((addr) && RR->node->shouldUsePathForZeroTierTraffic(tPtr, m_id, -1, addr)) { + if (RR->node->externalPathLookup(cc.tPtr, m_id, -1, addr)) { + if ((addr) && RR->node->shouldUsePathForZeroTierTraffic(cc.tPtr, m_id, -1, addr)) { int64_t < = m_lastTried[Endpoint(addr)]; - if ((now - lt) > ZT_PATH_MIN_TRY_INTERVAL) { - lt = now; - RR->t->tryingNewPath(tPtr, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL); - sent(now, m_sendProbe(tPtr, -1, addr, nullptr, 0, now)); + if ((cc.ticks - lt) > ZT_PATH_MIN_TRY_INTERVAL) { + lt = cc.ticks; + RR->t->tryingNewPath(cc, 0x84a10000, m_id, addr, InetAddress::NIL, 0, 0, Identity::NIL); + sent(cc, m_sendProbe(cc, -1, addr, nullptr, 0)); } } } @@ -318,7 +316,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) // 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)); + sent(cc, m_sendProbe(cc, -1, qi.target.ip(), nullptr, 0)); ++qi.iteration; goto requeue_item; @@ -340,7 +338,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) ports[pn++] = p; } if (pn > 0) - sent(now, m_sendProbe(tPtr, -1, qi.target.ip(), ports, pn, now)); + sent(cc, m_sendProbe(cc, -1, qi.target.ip(), ports, pn)); if (qi.iteration < 1023) goto requeue_item; @@ -354,7 +352,7 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) if (p > 65535) p -= 64512; // wrap back to 1024 tmp.setPort(p); - sent(now, m_sendProbe(tPtr, -1, tmp, nullptr, 0, now)); + sent(cc, m_sendProbe(cc, -1, tmp, nullptr, 0)); if (qi.iteration < ZT_NAT_T_PORT_SCAN_MAX) goto requeue_item; @@ -385,13 +383,13 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) for (unsigned int i = 0; i < m_alivePathCount; ++i) { if (needHello) { needHello = false; - const unsigned int bytes = hello(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), now); - m_paths[i]->sent(now, bytes); - sent(now, bytes); - m_lastSentHello = now; - } else if ((now - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { - m_paths[i]->send(RR, tPtr, reinterpret_cast(&randomJunk) + (i & 7U), 1, now); - sent(now, 1); + const unsigned int bytes = hello(cc, m_paths[i]->localSocket(), m_paths[i]->address()); + m_paths[i]->sent(cc, bytes); + sent(cc, bytes); + m_lastSentHello = cc.ticks; + } else if ((cc.ticks - m_paths[i]->lastOut()) >= ZT_PATH_KEEPALIVE_PERIOD) { + m_paths[i]->send(RR, cc, reinterpret_cast(&randomJunk) + (i & 7U), 1); + sent(cc, 1); } } @@ -399,34 +397,35 @@ void Peer::pulse(void *const tPtr, const int64_t now, const bool isRoot) if (needHello) { const SharedPtr< Peer > root(RR->topology->root()); if (root) { - const SharedPtr< Path > via(root->path(now)); + const SharedPtr< Path > via(root->path(cc)); if (via) { - const unsigned int bytes = hello(tPtr, via->localSocket(), via->address(), now); - via->sent(now, bytes); - root->relayed(now, bytes); - sent(now, bytes); - m_lastSentHello = now; + const unsigned int bytes = hello(cc, via->localSocket(), via->address()); + via->sent(cc, bytes); + root->relayed(cc, bytes); + sent(cc, bytes); + m_lastSentHello = cc.ticks; } } } // Clean m_lastTried for (Map< Endpoint, int64_t >::iterator i(m_lastTried.begin()); i != m_lastTried.end();) { - if ((now - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 4)) + if ((cc.ticks - i->second) > (ZT_PATH_MIN_TRY_INTERVAL * 4)) m_lastTried.erase(i++); else ++i; } } -void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries) +void Peer::contact(CallContext &cc, const Endpoint &ep, int tries) { static uint8_t foo = 0; RWMutex::Lock l(m_lock); // See if there's already a path to this endpoint and if so ignore it. if (ep.isInetAddr()) { - if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) - m_prioritizePaths(now); + if ((cc.ticks - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { + m_prioritizePaths(cc); + } for (unsigned int i = 0; i < m_alivePathCount; ++i) { if (m_paths[i]->address().ipsEqual(ep.ip())) return; @@ -435,15 +434,15 @@ void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries) // Check underlying path attempt rate limit. int64_t < = m_lastTried[ep]; - if ((now - lt) < ZT_PATH_MIN_TRY_INTERVAL) + if ((cc.ticks - lt) < ZT_PATH_MIN_TRY_INTERVAL) return; - lt = now; + lt = cc.ticks; // For IPv4 addresses we send a tiny packet with a low TTL, which helps to // traverse some NAT types. It has no effect otherwise. if (ep.isInetAddr() && ep.ip().isV4()) { ++foo; - RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast(&ep.ip()), &foo, 1, 2); + RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast(&ep.ip()), &foo, 1, 2); } // Make sure address is not already in the try queue. If so just update it. @@ -458,15 +457,15 @@ void Peer::contact(void *tPtr, const int64_t now, const Endpoint &ep, int tries) m_tryQueue.push_back(p_TryQueueItem(ep, -tries)); } -void Peer::resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now) +void Peer::resetWithinScope(CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily) { RWMutex::Lock l(m_lock); unsigned int pc = 0; for (unsigned int i = 0; i < m_alivePathCount; ++i) { - if ((m_paths[i]) && ((m_paths[i]->address().family() == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) { - const unsigned int bytes = m_sendProbe(tPtr, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0, now); - m_paths[i]->sent(now, bytes); - sent(now, bytes); + if ((m_paths[i]) && (((int)m_paths[i]->address().as.sa.sa_family == inetAddressFamily) && (m_paths[i]->address().ipScope() == scope))) { + const unsigned int bytes = m_sendProbe(cc, m_paths[i]->localSocket(), m_paths[i]->address(), nullptr, 0); + m_paths[i]->sent(cc, bytes); + sent(cc, bytes); } else if (pc != i) { m_paths[pc++] = m_paths[i]; } @@ -476,11 +475,11 @@ void Peer::resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddr m_paths[pc++].zero(); } -bool Peer::directlyConnected(int64_t now) +bool Peer::directlyConnected(CallContext &cc) { - if ((now - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { + if ((cc.ticks - m_lastPrioritizedPaths) > ZT_PEER_PRIORITIZE_PATHS_INTERVAL) { RWMutex::Lock l(m_lock); - m_prioritizePaths(now); + m_prioritizePaths(cc); return m_alivePathCount > 0; } else { RWMutex::RLock l(m_lock); @@ -496,19 +495,19 @@ void Peer::getAllPaths(Vector< SharedPtr< Path > > &paths) paths.assign(m_paths, m_paths + m_alivePathCount); } -void Peer::save(void *tPtr) const +void Peer::save(CallContext &cc) const { uint8_t buf[8 + ZT_PEER_MARSHAL_SIZE_MAX]; // Prefix each saved peer with the current timestamp. - Utils::storeBigEndian< uint64_t >(buf, (uint64_t)RR->node->now()); + Utils::storeBigEndian< uint64_t >(buf, (uint64_t)cc.clock); const int len = marshal(buf + 8); if (len > 0) { uint64_t id[2]; id[0] = m_id.address().toInt(); id[1] = 0; - RR->store->put(tPtr, ZT_STATE_OBJECT_PEER, id, 1, buf, (unsigned int)len + 8); + RR->store->put(cc, ZT_STATE_OBJECT_PEER, id, 1, buf, (unsigned int)len + 8); } } @@ -579,7 +578,7 @@ int Peer::marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept return p; } -int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept +int Peer::unmarshal(const int64_t ticks, const uint8_t *restrict data, const int len) noexcept { RWMutex::Lock l(m_lock); @@ -596,7 +595,7 @@ int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH, k); RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 16, k + 16); RR->localSecretCipher.decrypt(data + 1 + ZT_ADDRESS_LENGTH + 32, k + 32); - m_identityKey.set(new SymmetricKey(RR->node->now(), k)); + m_identityKey.set(new SymmetricKey(ticks, k)); Utils::burn(k, sizeof(k)); } @@ -611,7 +610,7 @@ int Peer::unmarshal(const uint8_t *restrict data, const int len) noexcept uint8_t k[ZT_SYMMETRIC_KEY_SIZE]; if (!RR->identity.agree(m_id, k)) return -1; - m_identityKey.set(new SymmetricKey(RR->node->now(), k)); + m_identityKey.set(new SymmetricKey(ticks, k)); Utils::burn(k, sizeof(k)); } @@ -673,10 +672,10 @@ struct _PathPriorityComparisonOperator } }; -void Peer::m_prioritizePaths(int64_t now) +void Peer::m_prioritizePaths(CallContext &cc) { // assumes _lock is locked for writing - m_lastPrioritizedPaths = now; + m_lastPrioritizedPaths = cc.ticks; if (m_alivePathCount > 0) { // Sort paths in descending order of priority. @@ -684,7 +683,7 @@ void Peer::m_prioritizePaths(int64_t now) // Let go of paths that have expired. for (unsigned int i = 0; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) { - if ((!m_paths[i]) || (!m_paths[i]->alive(now))) { + if ((!m_paths[i]) || (!m_paths[i]->alive(cc))) { m_alivePathCount = i; for (; i < ZT_MAX_PEER_NETWORK_PATHS; ++i) m_paths[i].zero(); @@ -694,7 +693,7 @@ void Peer::m_prioritizePaths(int64_t now) } } -unsigned int Peer::m_sendProbe(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts, int64_t now) +unsigned int Peer::m_sendProbe(CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, const unsigned int numPorts) { // Assumes m_lock is locked const SharedPtr< SymmetricKey > k(m_key()); @@ -709,17 +708,17 @@ unsigned int Peer::m_sendProbe(void *tPtr, int64_t localSocket, const InetAddres Protocol::armor(p, ZT_PROTO_MIN_PACKET_LENGTH, k, cipher()); - RR->expect->sending(packetId, now); + RR->expect->sending(packetId, cc.ticks); if (numPorts > 0) { InetAddress tmp(atAddress); for (unsigned int i = 0; i < numPorts; ++i) { tmp.setPort(ports[i]); - RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); + RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast(&tmp), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); } return ZT_PROTO_MIN_PACKET_LENGTH * numPorts; } else { - RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, -1, reinterpret_cast(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); + RR->cb.wirePacketSendFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, -1, reinterpret_cast(&atAddress), p, ZT_PROTO_MIN_PACKET_LENGTH, 0); return ZT_PROTO_MIN_PACKET_LENGTH; } } diff --git a/core/Peer.hpp b/core/Peer.hpp index f68f1ad7e..1f9b101fd 100644 --- a/core/Peer.hpp +++ b/core/Peer.hpp @@ -77,7 +77,7 @@ public: * @param peerIdentity The peer's identity * @return True if initialization was succcesful */ - bool init(const Identity &peerIdentity); + bool init(CallContext &cc, const Identity &peerIdentity); /** * @return This peer's ZT address (short for identity().address()) @@ -113,7 +113,7 @@ public: ZT_INLINE SharedPtr< const Locator > setLocator(const SharedPtr< const Locator > &loc, bool verify) noexcept { RWMutex::Lock l(m_lock); - if ((loc) && ((!m_locator) || (m_locator->timestamp() < loc->timestamp()))) { + if ((loc) && ((!m_locator) || (m_locator->revision() < loc->revision()))) { if ((!verify) || loc->verify(m_id)) m_locator = loc; } @@ -126,7 +126,6 @@ public: * This is called by the decode pipe when a packet is proven to be authentic * and appears to be valid. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param path Path over which packet was received * @param hops ZeroTier (not IP) hops * @param packetId Packet ID @@ -134,7 +133,7 @@ public: * @param inReVerb In-reply verb for OK or ERROR verbs */ void received( - void *tPtr, + CallContext &cc, const SharedPtr< Path > &path, unsigned int hops, uint64_t packetId, @@ -145,38 +144,36 @@ public: /** * Log sent data * - * @param now Current time * @param bytes Number of bytes written */ - ZT_INLINE void sent(const int64_t now, const unsigned int bytes) noexcept + ZT_INLINE void sent(CallContext &cc, const unsigned int bytes) noexcept { - m_lastSend = now; - m_outMeter.log(now, bytes); + m_lastSend = cc.ticks; + m_outMeter.log(cc.ticks, bytes); } /** * Called when traffic destined for a different peer is sent to this one * - * @param now Current time * @param bytes Number of bytes relayed */ - ZT_INLINE void relayed(const int64_t now, const unsigned int bytes) noexcept - { m_relayedMeter.log(now, bytes); } + ZT_INLINE void relayed(CallContext &cc, const unsigned int bytes) noexcept + { m_relayedMeter.log(cc.ticks, bytes); } /** * Get the current best direct path or NULL if none * * @return Current best path or NULL if there is no direct path */ - ZT_INLINE SharedPtr< Path > path(const int64_t now) noexcept + ZT_INLINE SharedPtr< Path > path(CallContext &cc) noexcept { - if (likely((now - m_lastPrioritizedPaths) < ZT_PEER_PRIORITIZE_PATHS_INTERVAL)) { + if (likely((cc.ticks - m_lastPrioritizedPaths) < ZT_PEER_PRIORITIZE_PATHS_INTERVAL)) { RWMutex::RLock l(m_lock); if (m_alivePathCount > 0) return m_paths[0]; } else { RWMutex::Lock l(m_lock); - m_prioritizePaths(now); + m_prioritizePaths(cc); if (m_alivePathCount > 0) return m_paths[0]; } @@ -186,16 +183,14 @@ public: /** * Send data to this peer over a specific path only * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param now Current time * @param data Data to send * @param len Length in bytes * @param via Path over which to send data (may or may not be an already-learned path for this peer) */ - ZT_INLINE void send(void *tPtr, int64_t now, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept + ZT_INLINE void send(CallContext &cc, const void *data, unsigned int len, const SharedPtr< Path > &via) noexcept { - via->send(RR, tPtr, data, len, now); - sent(now, len); + via->send(RR, cc, data, len); + sent(cc, len); } /** @@ -204,42 +199,34 @@ public: * If there is a working direct path it will be used. Otherwise the data will be * sent via a root server. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param now Current time * @param data Data to send * @param len Length in bytes */ - void send(void *tPtr, int64_t now, const void *data, unsigned int len) noexcept; + void send(CallContext &cc, const void *data, unsigned int len) noexcept; /** * Send a HELLO to this peer at a specified physical address. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param localSocket Local source socket * @param atAddress Destination address - * @param now Current time * @return Number of bytes sent */ - unsigned int hello(void *tPtr, int64_t localSocket, const InetAddress &atAddress, int64_t now); + unsigned int hello(CallContext &cc, int64_t localSocket, const InetAddress &atAddress); /** * Ping this peer if needed and/or perform other periodic tasks. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call - * @param now Current time * @param isRoot True if this peer is a root */ - void pulse(void *tPtr, int64_t now, bool isRoot); + void pulse(CallContext &cc, bool isRoot); /** * Attempt to contact this peer at a given endpoint. * - * @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, int tries = 1); + void contact(CallContext &cc, const Endpoint &ep, int tries = 1); /** * Reset paths within a given IP scope and address family @@ -249,12 +236,10 @@ public: * to our external IP or another system change that might invalidate * many or all current paths. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param scope IP scope * @param inetAddressFamily Family e.g. AF_INET - * @param now Current time */ - void resetWithinScope(void *tPtr, InetAddress::IpScope scope, int inetAddressFamily, int64_t now); + void resetWithinScope(CallContext &cc, InetAddress::IpScope scope, int inetAddressFamily); /** * @return Time of last receive of anything, whether direct or relayed @@ -372,7 +357,7 @@ public: /** * @return True if there is at least one alive direct path */ - bool directlyConnected(int64_t now); + bool directlyConnected(CallContext &cc); /** * Get all paths @@ -384,7 +369,7 @@ public: /** * Save the latest version of this peer to the data store */ - void save(void *tPtr) const; + void save(CallContext &cc) const; // NOTE: peer marshal/unmarshal only saves/restores the identity, locator, most // recent bootstrap address, and version information. @@ -393,15 +378,15 @@ public: int marshal(uint8_t data[ZT_PEER_MARSHAL_SIZE_MAX]) const noexcept; - int unmarshal(const uint8_t *restrict data, int len) noexcept; + int unmarshal(int64_t ticks, const uint8_t *restrict data, int len) noexcept; /** * Rate limit gate for inbound WHOIS requests */ - ZT_INLINE bool rateGateInboundWhoisRequest(const int64_t now) noexcept + ZT_INLINE bool rateGateInboundWhoisRequest(CallContext &cc) noexcept { - if ((now - m_lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { - m_lastWhoisRequestReceived = now; + if ((cc.ticks - m_lastWhoisRequestReceived) >= ZT_PEER_WHOIS_RATE_LIMIT) { + m_lastWhoisRequestReceived = cc.ticks; return true; } return false; @@ -410,10 +395,10 @@ public: /** * Rate limit gate for inbound ECHO requests */ - ZT_INLINE bool rateGateEchoRequest(const int64_t now) noexcept + ZT_INLINE bool rateGateEchoRequest(CallContext &cc) noexcept { - if ((now - m_lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { - m_lastEchoRequestReceived = now; + if ((cc.ticks - m_lastEchoRequestReceived) >= ZT_PEER_GENERAL_RATE_LIMIT) { + m_lastEchoRequestReceived = cc.ticks; return true; } return false; @@ -422,10 +407,10 @@ public: /** * Rate limit gate for inbound probes */ - ZT_INLINE bool rateGateProbeRequest(const int64_t now) noexcept + ZT_INLINE bool rateGateProbeRequest(CallContext &cc) noexcept { - if ((now - m_lastProbeReceived) > ZT_PEER_PROBE_RESPONSE_RATE_LIMIT) { - m_lastProbeReceived = now; + if ((cc.ticks - m_lastProbeReceived) > ZT_PEER_PROBE_RESPONSE_RATE_LIMIT) { + m_lastProbeReceived = cc.ticks; return true; } return false; @@ -447,10 +432,8 @@ public: } private: - void m_prioritizePaths(int64_t now); - - unsigned int m_sendProbe(void *tPtr, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts, int64_t now); - + void m_prioritizePaths(CallContext &cc); + unsigned int m_sendProbe(CallContext &cc, int64_t localSocket, const InetAddress &atAddress, const uint16_t *ports, unsigned int numPorts); void m_deriveSecondaryIdentityKeys() noexcept; ZT_INLINE SharedPtr< SymmetricKey > m_key() noexcept diff --git a/core/RevocationCredential.hpp b/core/RevocationCredential.hpp index 1439bd00e..fad326e5f 100644 --- a/core/RevocationCredential.hpp +++ b/core/RevocationCredential.hpp @@ -110,8 +110,8 @@ public: * @param RR Runtime environment to provide for peer lookup, etc. * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, void *tPtr) const noexcept - { return s_verify(RR, tPtr, *this); } + ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept + { return s_verify(RR, cc, *this); } static constexpr int marshalSizeMax() noexcept { return ZT_REVOCATION_MARSHAL_SIZE_MAX; } diff --git a/core/Salsa20.hpp b/core/Salsa20.hpp index a301d7e96..7a3cc8c8a 100644 --- a/core/Salsa20.hpp +++ b/core/Salsa20.hpp @@ -39,19 +39,26 @@ class Salsa20 : public TriviallyCopyable { public: #ifdef ZT_SALSA20_SSE - static constexpr bool accelerated() noexcept { return true; } + + static constexpr bool accelerated() noexcept + { return true; } + #else static constexpr bool accelerated() noexcept { return false; } #endif - ZT_INLINE Salsa20() noexcept {} - ZT_INLINE ~Salsa20() noexcept { Utils::burn(&_state,sizeof(_state)); } + ZT_INLINE Salsa20() noexcept + {} + + ZT_INLINE ~Salsa20() noexcept + { Utils::burn(&_state, sizeof(_state)); } /** * @param key 256-bit (32 byte) key * @param iv 64-bit initialization vector */ - ZT_INLINE Salsa20(const void *key,const void *iv) noexcept { init(key,iv); } + ZT_INLINE Salsa20(const void *key, const void *iv) noexcept + { init(key, iv); } /** * Initialize cipher @@ -59,7 +66,7 @@ public: * @param key Key bits * @param iv 64-bit initialization vector */ - void init(const void *key,const void *iv) noexcept; + void init(const void *key, const void *iv) noexcept; /** * Encrypt/decrypt data using Salsa20/12 @@ -68,7 +75,7 @@ public: * @param out Output buffer * @param bytes Length of data */ - void crypt12(const void *in,void *out,unsigned int bytes) noexcept; + void crypt12(const void *in, void *out, unsigned int bytes) noexcept; /** * Encrypt/decrypt data using Salsa20/20 @@ -77,10 +84,11 @@ public: * @param out Output buffer * @param bytes Length of data */ - void crypt20(const void *in,void *out,unsigned int bytes) noexcept; + void crypt20(const void *in, void *out, unsigned int bytes) noexcept; private: - union { + union + { #ifdef ZT_SALSA20_SSE __m128i v[4]; #endif // ZT_SALSA20_SSE diff --git a/core/ScopedPtr.hpp b/core/ScopedPtr.hpp index 963aeb6c6..6b7b67172 100644 --- a/core/ScopedPtr.hpp +++ b/core/ScopedPtr.hpp @@ -84,6 +84,6 @@ namespace std { template< typename T > ZT_INLINE void swap(ZeroTier::ScopedPtr< T > &a, ZeroTier::ScopedPtr< T > &b) noexcept { a.swap(b); } -} +} // namespace std #endif diff --git a/core/SelfAwareness.cpp b/core/SelfAwareness.cpp index 7bd490e0f..07f9f68bf 100644 --- a/core/SelfAwareness.cpp +++ b/core/SelfAwareness.cpp @@ -24,32 +24,12 @@ namespace ZeroTier { -class _ResetWithinScope -{ -public: - ZT_INLINE _ResetWithinScope(void *tPtr, int64_t now, int inetAddressFamily, InetAddress::IpScope scope) : - _now(now), - _tPtr(tPtr), - _family(inetAddressFamily), - _scope(scope) - {} - - ZT_INLINE void operator()(const SharedPtr< Peer > &p) - { p->resetWithinScope(_tPtr, _scope, _family, _now); } - -private: - int64_t _now; - void *_tPtr; - int _family; - InetAddress::IpScope _scope; -}; - SelfAwareness::SelfAwareness(const RuntimeEnvironment *renv) : RR(renv) { } -void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted, int64_t now) +void SelfAwareness::iam(CallContext &cc, const Identity &reporter, const int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted) { const InetAddress::IpScope scope = myPhysicalAddress.ipScope(); @@ -59,10 +39,10 @@ void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t rece Mutex::Lock l(m_phy_l); p_PhySurfaceEntry &entry = m_phy[p_PhySurfaceKey(reporter.address(), receivedOnLocalSocket, reporterPhysicalAddress, scope)]; - if ((trusted) && ((now - entry.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) { + if ((trusted) && ((cc.ticks - entry.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) && (!entry.mySurface.ipsEqual(myPhysicalAddress))) { // Changes to external surface reported by trusted peers causes path reset in this scope entry.mySurface = myPhysicalAddress; - entry.ts = now; + entry.timestampTicks = cc.ticks; entry.trusted = trusted; // Erase all entries in this scope that were not reported from this remote address to prevent 'thrashing' @@ -78,28 +58,28 @@ void SelfAwareness::iam(void *tPtr, const Identity &reporter, const int64_t rece Vector< SharedPtr< Peer > > peers, rootPeers; RR->topology->allPeers(peers, rootPeers); for(Vector< SharedPtr< Peer > >::const_iterator p(peers.begin());p!=peers.end();++p) - (*p)->resetWithinScope(tPtr, (InetAddress::IpScope)scope, myPhysicalAddress.family(), now); + (*p)->resetWithinScope(cc, (InetAddress::IpScope)scope, myPhysicalAddress.as.sa.sa_family); - RR->t->resettingPathsInScope(tPtr, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope); + RR->t->resettingPathsInScope(cc, 0x9afff100, reporter, reporterPhysicalAddress, entry.mySurface, myPhysicalAddress, scope); } else { // Otherwise just update DB to use to determine external surface info entry.mySurface = myPhysicalAddress; - entry.ts = now; + entry.timestampTicks = cc.ticks; entry.trusted = trusted; } } -void SelfAwareness::clean(int64_t now) +void SelfAwareness::clean(CallContext &cc) { Mutex::Lock l(m_phy_l); for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::iterator i(m_phy.begin()); i != m_phy.end();) { - if ((now - i->second.ts) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) + if ((cc.ticks - i->second.timestampTicks) >= ZT_SELFAWARENESS_ENTRY_TIMEOUT) m_phy.erase(i++); else ++i; } } -MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(const int64_t now) const +MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(CallContext &cc) const { MultiMap< unsigned int, InetAddress > r; @@ -108,7 +88,7 @@ MultiMap< unsigned int, InetAddress > SelfAwareness::externalAddresses(const int { Mutex::Lock l(m_phy_l); for (Map< p_PhySurfaceKey, p_PhySurfaceEntry >::const_iterator i(m_phy.begin()); i != m_phy.end(); ++i) { - if ((now - i->second.ts) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) + if ((cc.ticks - i->second.timestampTicks) < ZT_SELFAWARENESS_ENTRY_TIMEOUT) ++counts[i->second.mySurface]; } } diff --git a/core/SelfAwareness.hpp b/core/SelfAwareness.hpp index ebf63d585..6b5ccc853 100644 --- a/core/SelfAwareness.hpp +++ b/core/SelfAwareness.hpp @@ -19,6 +19,7 @@ #include "Containers.hpp" #include "Address.hpp" #include "Mutex.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -44,24 +45,20 @@ public: * @param reporterPhysicalAddress Physical address that reporting peer seems to have * @param myPhysicalAddress Physical address that peer says we have * @param trusted True if this peer is trusted as an authority to inform us of external address changes - * @param now Current time */ - void iam(void *tPtr, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted, int64_t now); + void iam(CallContext &cc, const Identity &reporter, int64_t receivedOnLocalSocket, const InetAddress &reporterPhysicalAddress, const InetAddress &myPhysicalAddress, bool trusted); /** * Clean up database periodically - * - * @param now Current time */ - void clean(int64_t now); + void clean(CallContext &cc); /** * Get external address consensus, which is the statistical "mode" of external addresses. * - * @param now Current time * @return Map of count to IP/port representing how many endpoints reported each address */ - MultiMap< unsigned int, InetAddress > externalAddresses(int64_t now) const; + MultiMap< unsigned int, InetAddress > externalAddresses(CallContext &cc) const; private: struct p_PhySurfaceKey @@ -108,13 +105,13 @@ private: struct p_PhySurfaceEntry { InetAddress mySurface; - int64_t ts; + int64_t timestampTicks; bool trusted; - ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), ts(0), trusted(false) + ZT_INLINE p_PhySurfaceEntry() noexcept: mySurface(), timestampTicks(0), trusted(false) {} - ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), ts(t), trusted(false) + ZT_INLINE p_PhySurfaceEntry(const InetAddress &a, const int64_t t) noexcept: mySurface(a), timestampTicks(t), trusted(false) {} }; diff --git a/core/SharedPtr.hpp b/core/SharedPtr.hpp index b54a6b488..b77a33dbb 100644 --- a/core/SharedPtr.hpp +++ b/core/SharedPtr.hpp @@ -33,7 +33,7 @@ public: {} explicit ZT_INLINE SharedPtr(T *obj) noexcept: m_ptr(obj) - { if (likely(obj != nullptr)) const_cast *>(&(obj->__refCount))->fetch_add(1, std::memory_order_relaxed); } + { if (likely(obj != nullptr)) const_cast *>(&(obj->__refCount))->fetch_add(1, std::memory_order_acquire); } ZT_INLINE SharedPtr(const SharedPtr &sp) noexcept: m_ptr(sp._getAndInc()) {} @@ -54,7 +54,7 @@ public: ZT_INLINE void set(T *ptr) noexcept { _release(); - const_cast *>(&((m_ptr = ptr)->__refCount))->fetch_add(1, std::memory_order_relaxed); + const_cast *>(&((m_ptr = ptr)->__refCount))->fetch_add(1, std::memory_order_acquire); } /** @@ -122,7 +122,7 @@ public: { if (likely(m_ptr != nullptr)) { int one = 1; - if (const_cast *>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0)) { + if (const_cast *>(&(m_ptr->__refCount))->compare_exchange_strong(one, (int)0, std::memory_order_acq_rel)) { delete m_ptr; m_ptr = nullptr; return true; @@ -145,14 +145,6 @@ public: return 0; } - /** - * Cast this SharedPtr<> to one that holds a const instance of the type - * - * @return "this" casted in place to hold "const T" - */ - ZT_INLINE const SharedPtr &constify() const noexcept - { return reinterpret_cast< const SharedPtr >(*this); } - ZT_INLINE unsigned long hashCode() const noexcept { return (unsigned long)Utils::hash64((uint64_t)((uintptr_t)m_ptr)); } @@ -178,13 +170,13 @@ private: ZT_INLINE T *_getAndInc() const noexcept { if (likely(m_ptr != nullptr)) - const_cast *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_relaxed); + const_cast *>(&(m_ptr->__refCount))->fetch_add(1, std::memory_order_acquire); return m_ptr; } ZT_INLINE void _release() const noexcept { - if (unlikely((m_ptr != nullptr)&&(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_relaxed) <= 1))) + if (unlikely((m_ptr != nullptr)&&(const_cast *>(&(m_ptr->__refCount))->fetch_sub(1, std::memory_order_release) <= 1))) delete m_ptr; } @@ -197,9 +189,13 @@ private: namespace std { template< typename T > -ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept +ZT_MAYBE_UNUSED ZT_INLINE void swap(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept { a.swap(b); } +template< typename T > +ZT_MAYBE_UNUSED ZT_INLINE void move(ZeroTier::SharedPtr< T > &a, ZeroTier::SharedPtr< T > &b) noexcept +{ a.move(b); } + } // namespace std #endif diff --git a/core/Store.hpp b/core/Store.hpp index 7cc8a399f..0c0ac9221 100644 --- a/core/Store.hpp +++ b/core/Store.hpp @@ -17,6 +17,7 @@ #include "Constants.hpp" #include "Containers.hpp" #include "RuntimeEnvironment.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -32,18 +33,17 @@ public: /** * Get a state object * - * @param tPtr Thread pointer to pass through * @param type Object type * @param id Object ID * @param idSize Size of object ID in qwords * @return Data or empty vector if not found */ - ZT_INLINE Vector< uint8_t > get(void *tPtr, ZT_StateObjectType type, const uint64_t *id, unsigned int idSize) const + ZT_INLINE Vector< uint8_t > get(CallContext &cc, ZT_StateObjectType type, const uint64_t *id, unsigned int idSize) const { Vector< uint8_t > dv; void *data = nullptr; void (*freeFunc)(void *) = nullptr; - const int r = RR->cb.stateGetFunction(reinterpret_cast(RR->node), RR->uPtr, tPtr, type, id, idSize, &data, &freeFunc); + const int r = RR->cb.stateGetFunction(reinterpret_cast(RR->node), RR->uPtr, cc.tPtr, type, id, idSize, &data, &freeFunc); if (r > 0) dv.assign(reinterpret_cast(data), reinterpret_cast(data) + r); if ((data) && (freeFunc)) @@ -54,26 +54,24 @@ public: /** * Store a state object * - * @param tPtr Thread pointer to pass through * @param type Object type * @param id Object ID * @param idSize Size of object ID in qwords * @param data Data to store * @param len Length of data */ - ZT_INLINE void put(void *const tPtr, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept - { RR->cb.statePutFunction(reinterpret_cast(this), RR->uPtr, tPtr, type, id, idSize, data, (int)len); } + ZT_INLINE void put(CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize, const void *const data, const unsigned int len) noexcept + { RR->cb.statePutFunction(reinterpret_cast(this), RR->uPtr, cc.tPtr, type, id, idSize, data, (int)len); } /** * Erase a state object from the object store * - * @param tPtr Thread pointer to pass through * @param type Object type * @param id Object ID * @param idSize Size of object ID in qwords */ - ZT_INLINE void erase(void *const tPtr, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept - { RR->cb.statePutFunction(reinterpret_cast(this), RR->uPtr, tPtr, type, id, idSize, nullptr, -1); } + ZT_INLINE void erase(CallContext &cc, ZT_StateObjectType type, const uint64_t *const id, const unsigned int idSize) noexcept + { RR->cb.statePutFunction(reinterpret_cast(this), RR->uPtr, cc.tPtr, type, id, idSize, nullptr, -1); } private: const RuntimeEnvironment *RR; diff --git a/core/TagCredential.hpp b/core/TagCredential.hpp index a20b7d4d9..6ca4fbb5c 100644 --- a/core/TagCredential.hpp +++ b/core/TagCredential.hpp @@ -84,6 +84,9 @@ public: ZT_INLINE int64_t timestamp() const noexcept { return m_ts; } + ZT_INLINE int64_t revision() const noexcept + { return m_ts; } + ZT_INLINE const Address &issuedTo() const noexcept { return m_issuedTo; } @@ -110,8 +113,8 @@ public: * @param RR Runtime environment to allow identity lookup for signedBy * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call */ - ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, void *tPtr) const noexcept - { return s_verify(RR, tPtr, *this); } + ZT_INLINE Credential::VerifyResult verify(const RuntimeEnvironment *RR, CallContext &cc) const noexcept + { return s_verify(RR, cc, *this); } static constexpr int marshalSizeMax() noexcept { return ZT_TAG_MARSHAL_SIZE_MAX; } diff --git a/core/Topology.cpp b/core/Topology.cpp index fe5919a23..556eb1e57 100644 --- a/core/Topology.cpp +++ b/core/Topology.cpp @@ -13,20 +13,22 @@ #include "Topology.hpp" #include "Defaults.hpp" +#include "TrustStore.hpp" +#include "Locator.hpp" namespace ZeroTier { -Topology::Topology(const RuntimeEnvironment *renv, void *tPtr, const int64_t now) : +Topology::Topology(const RuntimeEnvironment *renv, CallContext &cc) : RR(renv) {} -SharedPtr< Peer > Topology::add(void *tPtr, const SharedPtr< Peer > &peer) +SharedPtr< Peer > Topology::add(CallContext &cc, const SharedPtr< Peer > &peer) { RWMutex::Lock _l(m_peers_l); SharedPtr< Peer > &hp = m_peers[peer->address()]; if (hp) return hp; - m_loadCached(tPtr, peer->address(), hp); + m_loadCached(cc, peer->address(), hp); if (hp) return hp; hp = peer; @@ -48,13 +50,13 @@ void Topology::allPeers(Vector< SharedPtr< Peer > > &allPeers, Vector< SharedPtr } } -void Topology::doPeriodicTasks(void *tPtr, const int64_t now) +void Topology::doPeriodicTasks(CallContext &cc) { // Get a list of root peer pointer addresses for filtering during peer cleanup. Vector< uintptr_t > rootLookup; { Mutex::Lock l(m_roots_l); - m_rankRoots(now); + m_rankRoots(); rootLookup.reserve(m_roots.size()); for (Vector< SharedPtr< Peer > >::const_iterator r(m_roots.begin()); r != m_roots.end(); ++r) rootLookup.push_back((uintptr_t)r->ptr()); @@ -69,7 +71,7 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now) RWMutex::RLock l1(m_peers_l); for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) { // TODO: also delete if the peer has not exchanged meaningful communication in a while, such as a network frame or non-trivial control packet. - if (((now - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (std::find(rootLookup.begin(), rootLookup.end(), (uintptr_t)(i->second.ptr())) == rootLookup.end())) + if (((cc.ticks - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (std::find(rootLookup.begin(), rootLookup.end(), (uintptr_t)(i->second.ptr())) == rootLookup.end())) toDelete.push_back(i->first); } } @@ -86,7 +88,7 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now) } } if (toSave) - toSave->save(tPtr); + toSave->save(cc); } } } @@ -117,11 +119,37 @@ void Topology::doPeriodicTasks(void *tPtr, const int64_t now) } } -void Topology::saveAll(void *tPtr) +void Topology::trustStoreChanged(CallContext &cc) +{ + Map< Identity, SharedPtr< const Locator > > roots(RR->ts->roots()); + + Vector< SharedPtr< Peer > > newRootList; + newRootList.reserve(roots.size()); + + for (Map< Identity, SharedPtr< const Locator > >::const_iterator r(roots.begin()); r != roots.end(); ++r) { + SharedPtr< Peer > root(this->peer(cc, r->first.address(), true)); + if (!root) { + root.set(new Peer(RR)); + root->init(cc, r->first); + root = this->add(cc, root); + } + newRootList.push_back(root); + if (r->second) + root->setLocator(r->second, true); + } + + { + Mutex::Lock l(m_roots_l); + m_roots.swap(newRootList); + m_rankRoots(); + } +} + +void Topology::saveAll(CallContext &cc) { RWMutex::RLock l(m_peers_l); for (Map< Address, SharedPtr< Peer > >::iterator i(m_peers.begin()); i != m_peers.end(); ++i) - i->second->save(tPtr); + i->second->save(cc); } struct p_RootRankingComparisonOperator @@ -147,7 +175,7 @@ struct p_RootRankingComparisonOperator } }; -void Topology::m_rankRoots(const int64_t now) +void Topology::m_rankRoots() { // assumes m_roots is locked if (unlikely(m_roots.empty())) { @@ -162,7 +190,7 @@ void Topology::m_rankRoots(const int64_t now) } } -void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer) +void Topology::m_loadCached(CallContext &cc, const Address &zta, SharedPtr< Peer > &peer) { // does not require any locks to be held @@ -170,19 +198,19 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &p uint64_t id[2]; id[0] = zta.toInt(); id[1] = 0; - Vector< uint8_t > data(RR->store->get(tPtr, ZT_STATE_OBJECT_PEER, id, 1)); + Vector< uint8_t > data(RR->store->get(cc, ZT_STATE_OBJECT_PEER, id, 1)); if (data.size() > 8) { const uint8_t *d = data.data(); int dl = (int)data.size(); const int64_t ts = (int64_t)Utils::loadBigEndian< uint64_t >(d); Peer *const p = new Peer(RR); - int n = p->unmarshal(d + 8, dl - 8); + int n = p->unmarshal(cc.ticks, d + 8, dl - 8); if (n < 0) { delete p; return; } - if ((RR->node->now() - ts) < ZT_PEER_GLOBAL_TIMEOUT) { + if ((cc.ticks - ts) < ZT_PEER_GLOBAL_TIMEOUT) { // TODO: handle many peers, same address (?) peer.set(p); return; @@ -193,10 +221,10 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &p } } -SharedPtr< Peer > Topology::m_peerFromCached(void *tPtr, const Address &zta) +SharedPtr< Peer > Topology::m_peerFromCached(CallContext &cc, const Address &zta) { SharedPtr< Peer > p; - m_loadCached(tPtr, zta, p); + m_loadCached(cc, zta, p); if (p) { RWMutex::Lock l(m_peers_l); SharedPtr< Peer > &hp = m_peers[zta]; diff --git a/core/Topology.hpp b/core/Topology.hpp index 359a981bc..f4e329cf6 100644 --- a/core/Topology.hpp +++ b/core/Topology.hpp @@ -28,6 +28,7 @@ #include "Certificate.hpp" #include "Containers.hpp" #include "Spinlock.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -39,7 +40,7 @@ class RuntimeEnvironment; class Topology { public: - Topology(const RuntimeEnvironment *renv, void *tPtr, int64_t now); + Topology(const RuntimeEnvironment *renv, CallContext &cc); /** * Add peer to database @@ -47,21 +48,19 @@ public: * This will not replace existing peers. In that case the existing peer * record is returned. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param peer Peer to add * @return New or existing peer (should replace 'peer') */ - SharedPtr< Peer > add(void *tPtr, const SharedPtr< Peer > &peer); + SharedPtr< Peer > add(CallContext &cc, const SharedPtr< Peer > &peer); /** * Get a peer from its address * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param zta ZeroTier address of peer * @param loadFromCached If false do not load from cache if not in memory (default: true) * @return Peer or NULL if not found */ - ZT_INLINE SharedPtr< Peer > peer(void *tPtr, const Address &zta, const bool loadFromCached = true) + ZT_INLINE SharedPtr< Peer > peer(CallContext &cc, const Address &zta, const bool loadFromCached = true) { { RWMutex::RLock l(m_peers_l); @@ -70,7 +69,7 @@ public: return ap->second; } if (loadFromCached) - return m_peerFromCached(tPtr, zta); + return m_peerFromCached(cc, zta); return SharedPtr< Peer >(); } @@ -125,34 +124,34 @@ public: /** * Do periodic tasks such as database cleanup, cert cleanup, root ranking, etc. - * - * @param tPtr Thread pointer - * @param now Current time */ - void doPeriodicTasks(void *tPtr, int64_t now); + void doPeriodicTasks(CallContext &cc); /** * Rank root servers in descending order of quality * * @param now Current time */ - ZT_INLINE void rankRoots(int64_t now) + ZT_INLINE void rankRoots(CallContext &cc) { Mutex::Lock l(m_roots_l); - m_rankRoots(now); + m_rankRoots(); } /** - * Save all currently known peers to data store - * - * @param tPtr Thread pointer + * Perform internal updates based on changes in the trust store */ - void saveAll(void *tPtr); + void trustStoreChanged(CallContext &cc); + + /** + * Save all currently known peers to data store + */ + void saveAll(CallContext &cc); private: - void m_rankRoots(int64_t now); - void m_loadCached(void *tPtr, const Address &zta, SharedPtr< Peer > &peer); - SharedPtr< Peer > m_peerFromCached(void *tPtr, const Address &zta); + void m_rankRoots(); + void m_loadCached(CallContext &cc, const Address &zta, SharedPtr< Peer > &peer); + SharedPtr< Peer > m_peerFromCached(CallContext &cc, const Address &zta); SharedPtr< Path > m_newPath(int64_t l, const InetAddress &r, const Path::Key &k); const RuntimeEnvironment *const RR; diff --git a/core/Trace.cpp b/core/Trace.cpp index 7da6b247a..5b5749e19 100644 --- a/core/Trace.cpp +++ b/core/Trace.cpp @@ -29,7 +29,7 @@ Trace::Trace(const RuntimeEnvironment *renv) : } void Trace::unexpectedError( - void *tPtr, + CallContext &cc, uint32_t codeLocation, const char *message, ...) @@ -39,17 +39,17 @@ void Trace::unexpectedError( Dictionary::append(buf, ZT_TRACE_FIELD_CODE_LOCATION, codeLocation); Dictionary::append(buf, ZT_TRACE_FIELD_MESSAGE, message); buf.push_back(0); - RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); + RR->node->postEvent(cc.tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_resettingPathsInScope( - void *const tPtr, - const uint32_t codeLocation, +void Trace::m_resettingPathsInScope( + void *tPtr, + uint32_t codeLocation, const Identity &reporter, const InetAddress &from, const InetAddress &oldExternal, const InetAddress &newExternal, - const InetAddress::IpScope scope) + ZT_InetAddress_IpScope scope) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE); @@ -67,14 +67,14 @@ void Trace::_resettingPathsInScope( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_tryingNewPath( - void *const tPtr, - const uint32_t codeLocation, +void Trace::m_tryingNewPath( + void *tPtr, + uint32_t codeLocation, const Identity &trying, const InetAddress &physicalAddress, const InetAddress &triggerAddress, - const uint64_t triggeringPacketId, - const uint8_t triggeringPacketVerb, + uint64_t triggeringPacketId, + uint8_t triggeringPacketVerb, const Identity &triggeringPeer) { if ((trying)&&(physicalAddress)) { @@ -94,10 +94,10 @@ void Trace::_tryingNewPath( } } -void Trace::_learnedNewPath( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t packetId, +void Trace::m_learnedNewPath( + void *tPtr, + uint32_t codeLocation, + uint64_t packetId, const Identity &peerIdentity, const InetAddress &physicalAddress, const InetAddress &replaced) @@ -117,16 +117,16 @@ void Trace::_learnedNewPath( } } -void Trace::_incomingPacketDropped( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t packetId, - const uint64_t networkId, +void Trace::m_incomingPacketDropped( + void *tPtr, + uint32_t codeLocation, + uint64_t packetId, + uint64_t networkId, const Identity &peerIdentity, const InetAddress &physicalAddress, - const uint8_t hops, - const uint8_t verb, - const ZT_TracePacketDropReason reason) + uint8_t hops, + uint8_t verb, + ZT_TracePacketDropReason reason) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED); @@ -144,16 +144,16 @@ void Trace::_incomingPacketDropped( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_outgoingNetworkFrameDropped( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t networkId, +void Trace::m_outgoingNetworkFrameDropped( + void *tPtr, + uint32_t codeLocation, + uint64_t networkId, const MAC &sourceMac, const MAC &destMac, - const uint16_t etherType, - const uint16_t frameLength, + uint16_t etherType, + uint16_t frameLength, const uint8_t *frameData, - const ZT_TraceFrameDropReason reason) + ZT_TraceFrameDropReason reason) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL1_INCOMING_PACKET_DROPPED); @@ -170,21 +170,21 @@ void Trace::_outgoingNetworkFrameDropped( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_incomingNetworkFrameDropped( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t networkId, +void Trace::m_incomingNetworkFrameDropped( + void *tPtr, + uint32_t codeLocation, + uint64_t networkId, const MAC &sourceMac, const MAC &destMac, const uint16_t etherType, const Identity &peerIdentity, const InetAddress &physicalAddress, - const uint8_t hops, - const uint16_t frameLength, + uint8_t hops, + uint16_t frameLength, const uint8_t *frameData, - const uint8_t verb, - const bool credentialRequestSent, - const ZT_TraceFrameDropReason reason) + uint8_t verb, + bool credentialRequestSent, + ZT_TraceFrameDropReason reason) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_INCOMING_FRAME_DROPPED); @@ -207,10 +207,10 @@ void Trace::_incomingNetworkFrameDropped( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_networkConfigRequestSent( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t networkId) +void Trace::m_networkConfigRequestSent( + void *tPtr, + uint32_t codeLocation, + uint64_t networkId) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CONFIG_REQUESTED); @@ -220,25 +220,25 @@ void Trace::_networkConfigRequestSent( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_networkFilter( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t networkId, - const uint8_t primaryRuleSetLog[512], - const uint8_t matchingCapabilityRuleSetLog[512], - const uint32_t matchingCapabilityId, - const int64_t matchingCapabilityTimestamp, +void Trace::m_networkFilter( + void *tPtr, + uint32_t codeLocation, + uint64_t networkId, + const uint8_t *primaryRuleSetLog, + const uint8_t *matchingCapabilityRuleSetLog, + uint32_t matchingCapabilityId, + int64_t matchingCapabilityTimestamp, const Address &source, const Address &dest, const MAC &sourceMac, const MAC &destMac, - const uint16_t frameLength, + uint16_t frameLength, const uint8_t *frameData, - const uint16_t etherType, - const uint16_t vlanId, - const bool noTee, - const bool inbound, - const int accept) + uint16_t etherType, + uint16_t vlanId, + bool noTee, + bool inbound, + int accept) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_FILTER); @@ -266,15 +266,15 @@ void Trace::_networkFilter( RR->node->postEvent(tPtr, ZT_EVENT_TRACE, buf.data()); } -void Trace::_credentialRejected( - void *const tPtr, - const uint32_t codeLocation, - const uint64_t networkId, +void Trace::m_credentialRejected( + void *tPtr, + uint32_t codeLocation, + uint64_t networkId, const Identity &identity, - const uint32_t credentialId, - const int64_t credentialTimestamp, - const uint8_t credentialType, - const ZT_TraceCredentialRejectionReason reason) + uint32_t credentialId, + int64_t credentialTimestamp, + uint8_t credentialType, + ZT_TraceCredentialRejectionReason reason) { FCV< uint8_t, 4096 > buf; Dictionary::append(buf, ZT_TRACE_FIELD_TYPE, ZT_TRACE_VL2_NETWORK_CREDENTIAL_REJECTED); diff --git a/core/Trace.hpp b/core/Trace.hpp index d9f6eff9e..bb815382e 100644 --- a/core/Trace.hpp +++ b/core/Trace.hpp @@ -22,6 +22,7 @@ #include "MAC.hpp" #include "Containers.hpp" #include "Utils.hpp" +#include "CallContext.hpp" #define ZT_TRACE_F_VL1 0x01U #define ZT_TRACE_F_VL2 0x02U @@ -31,25 +32,15 @@ namespace ZeroTier { class RuntimeEnvironment; - class Identity; - class Peer; - class Path; - class Network; - class MembershipCredential; - class OwnershipCredential; - class RevocationCredential; - class TagCredential; - class CapabilityCredential; - struct NetworkConfig; /** @@ -73,31 +64,25 @@ public: uint8_t l[ZT_MAX_NETWORK_RULES / 2]; // ZT_MAX_NETWORK_RULES 4-bit fields ZT_INLINE void log(const unsigned int rn, const uint8_t thisRuleMatches, const uint8_t thisSetMatches) noexcept - { - l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U); - } + { l[rn >> 1U] |= (((thisRuleMatches + 1U) << 2U) | (thisSetMatches + 1U)) << ((rn & 1U) << 2U); } ZT_INLINE void logSkipped(const unsigned int rn, const uint8_t thisSetMatches) noexcept - { - l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); - } + { l[rn >> 1U] |= (thisSetMatches + 1U) << ((rn & 1U) << 2U); } ZT_INLINE void clear() noexcept - { - memoryZero(this); - } + { memoryZero(this); } }; explicit Trace(const RuntimeEnvironment *renv); void unexpectedError( - void *tPtr, + CallContext &cc, uint32_t codeLocation, const char *message, ...); ZT_INLINE void resettingPathsInScope( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, const Identity &reporter, const InetAddress &from, @@ -105,12 +90,12 @@ public: const InetAddress &newExternal, const InetAddress::IpScope scope) { - if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) - _resettingPathsInScope(tPtr, codeLocation, reporter, from, oldExternal, newExternal, scope); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0)) + m_resettingPathsInScope(cc.tPtr, codeLocation, reporter, from, oldExternal, newExternal, scope); } ZT_INLINE void tryingNewPath( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, const Identity &trying, const InetAddress &physicalAddress, @@ -119,24 +104,24 @@ public: uint8_t triggeringPacketVerb, const Identity &triggeringPeer) { - if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) - _tryingNewPath(tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0)) + m_tryingNewPath(cc.tPtr, codeLocation, trying, physicalAddress, triggerAddress, triggeringPacketId, triggeringPacketVerb, triggeringPeer); } ZT_INLINE void learnedNewPath( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t packetId, const Identity &peerIdentity, const InetAddress &physicalAddress, const InetAddress &replaced) { - if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) - _learnedNewPath(tPtr, codeLocation, packetId, peerIdentity, physicalAddress, replaced); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0)) + m_learnedNewPath(cc.tPtr, codeLocation, packetId, peerIdentity, physicalAddress, replaced); } ZT_INLINE void incomingPacketDropped( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t packetId, uint64_t networkId, @@ -146,12 +131,12 @@ public: uint8_t verb, const ZT_TracePacketDropReason reason) { - if ((m_traceFlags & ZT_TRACE_F_VL1) != 0) - _incomingPacketDropped(tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL1) != 0)) + m_incomingPacketDropped(cc.tPtr, codeLocation, packetId, networkId, peerIdentity, physicalAddress, hops, verb, reason); } ZT_INLINE void outgoingNetworkFrameDropped( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t networkId, const MAC &sourceMac, @@ -161,12 +146,12 @@ public: const uint8_t *frameData, ZT_TraceFrameDropReason reason) { - if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) - _outgoingNetworkFrameDropped(tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0)) + m_outgoingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, frameLength, frameData, reason); } ZT_INLINE void incomingNetworkFrameDropped( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t networkId, const MAC &sourceMac, @@ -181,21 +166,21 @@ public: bool credentialRequestSent, ZT_TraceFrameDropReason reason) { - if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) - _incomingNetworkFrameDropped(tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0)) + m_incomingNetworkFrameDropped(cc.tPtr, codeLocation, networkId, sourceMac, destMac, etherType, peerIdentity, physicalAddress, hops, frameLength, frameData, verb, credentialRequestSent, reason); } ZT_INLINE void networkConfigRequestSent( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t networkId) { - if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) - _networkConfigRequestSent(tPtr, codeLocation, networkId); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0)) + m_networkConfigRequestSent(cc.tPtr, codeLocation, networkId); } ZT_INLINE void networkFilter( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t networkId, const uint8_t primaryRuleSetLog[512], @@ -214,9 +199,9 @@ public: bool inbound, int accept) { - if ((m_traceFlags & ZT_TRACE_F_VL2_FILTER) != 0) { - _networkFilter( - tPtr, + if (unlikely((m_traceFlags & ZT_TRACE_F_VL2_FILTER) != 0)) { + m_networkFilter( + cc.tPtr, codeLocation, networkId, primaryRuleSetLog, @@ -238,7 +223,7 @@ public: } ZT_INLINE void credentialRejected( - void *const tPtr, + CallContext &cc, const uint32_t codeLocation, uint64_t networkId, const Identity &identity, @@ -247,12 +232,12 @@ public: uint8_t credentialType, ZT_TraceCredentialRejectionReason reason) { - if ((m_traceFlags & ZT_TRACE_F_VL2) != 0) - _credentialRejected(tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason); + if (unlikely((m_traceFlags & ZT_TRACE_F_VL2) != 0)) + m_credentialRejected(cc.tPtr, codeLocation, networkId, identity, credentialId, credentialTimestamp, credentialType, reason); } private: - void _resettingPathsInScope( + void m_resettingPathsInScope( void *tPtr, uint32_t codeLocation, const Identity &reporter, @@ -261,7 +246,7 @@ private: const InetAddress &newExternal, InetAddress::IpScope scope); - void _tryingNewPath( + void m_tryingNewPath( void *tPtr, uint32_t codeLocation, const Identity &trying, @@ -271,7 +256,7 @@ private: uint8_t triggeringPacketVerb, const Identity &triggeringPeer); - void _learnedNewPath( + void m_learnedNewPath( void *tPtr, uint32_t codeLocation, uint64_t packetId, @@ -279,7 +264,7 @@ private: const InetAddress &physicalAddress, const InetAddress &replaced); - void _incomingPacketDropped( + void m_incomingPacketDropped( void *tPtr, uint32_t codeLocation, uint64_t packetId, @@ -290,7 +275,7 @@ private: uint8_t verb, ZT_TracePacketDropReason reason); - void _outgoingNetworkFrameDropped( + void m_outgoingNetworkFrameDropped( void *tPtr, uint32_t codeLocation, uint64_t networkId, @@ -301,7 +286,7 @@ private: const uint8_t *frameData, ZT_TraceFrameDropReason reason); - void _incomingNetworkFrameDropped( + void m_incomingNetworkFrameDropped( void *tPtr, uint32_t codeLocation, uint64_t networkId, @@ -317,17 +302,17 @@ private: bool credentialRequestSent, ZT_TraceFrameDropReason reason); - void _networkConfigRequestSent( + void m_networkConfigRequestSent( void *tPtr, uint32_t codeLocation, uint64_t networkId); - void _networkFilter( + void m_networkFilter( void *tPtr, uint32_t codeLocation, uint64_t networkId, - const uint8_t primaryRuleSetLog[512], - const uint8_t matchingCapabilityRuleSetLog[512], + const uint8_t *primaryRuleSetLog, + const uint8_t *matchingCapabilityRuleSetLog, uint32_t matchingCapabilityId, int64_t matchingCapabilityTimestamp, const Address &source, @@ -342,7 +327,7 @@ private: bool inbound, int accept); - void _credentialRejected( + void m_credentialRejected( void *tPtr, uint32_t codeLocation, uint64_t networkId, diff --git a/core/TrustStore.cpp b/core/TrustStore.cpp index e090399d7..7b26554d7 100644 --- a/core/TrustStore.cpp +++ b/core/TrustStore.cpp @@ -41,7 +41,7 @@ Map< Identity, SharedPtr< const Locator > > TrustStore::roots() if (likely((id != nullptr) && (*id))) { // sanity check SharedPtr< const Locator > &existingLoc = r[*id]; const Locator *const loc = reinterpret_cast((*c)->certificate().subject.identities[j].locator); - if ((loc != nullptr) && ((!existingLoc) || (existingLoc->timestamp() < loc->timestamp()))) + if ((loc != nullptr) && ((!existingLoc) || (existingLoc->revision() < loc->revision()))) existingLoc.set(new Locator(*loc)); } } @@ -63,17 +63,6 @@ Vector< SharedPtr< TrustStore::Entry > > TrustStore::all(const bool includeRejec return r; } -Vector< SharedPtr< TrustStore::Entry > > TrustStore::rejects() const -{ - RWMutex::RLock l(m_lock); - Vector< SharedPtr< Entry > > r; - for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) { - if (c->second->error() != ZT_CERTIFICATE_ERROR_NONE) - r.push_back(c->second); - } - return r; -} - void TrustStore::add(const Certificate &cert, const unsigned int localTrust) { RWMutex::Lock l(m_lock); @@ -105,7 +94,7 @@ static bool p_validatePath(const Map< H384, Vector< SharedPtr< TrustStore::Entry return false; } -void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const purge) +bool TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const purge) { RWMutex::Lock l(m_lock); @@ -113,15 +102,21 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const // signature check here since that's done when they're taken out of the add queue. bool errorStateModified = false; for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end(); ++c) { - const ZT_CertificateError err = c->second->m_certificate.verify(clock, false); - errorStateModified |= (c->second->m_error.exchange((int)err, std::memory_order_relaxed) != (int)err); + const ZT_CertificateError err = c->second->error(); + if ((err != ZT_CERTIFICATE_ERROR_HAVE_NEWER_CERT) && (err != ZT_CERTIFICATE_ERROR_INVALID_CHAIN)) { + const ZT_CertificateError newErr = c->second->m_certificate.verify(clock, false); + if (newErr != err) { + c->second->m_error.store((int)newErr, std::memory_order_relaxed); + errorStateModified = true; + } + } } // If no certificate error statuses changed and there are no new certificates to // add, there is nothing to do and we don't need to do more expensive path validation // and structure rebuilding. if ((!errorStateModified) && (m_addQueue.empty()) && (m_deleteQueue.empty())) - return; + return false; // Add new certificates to m_bySerial, which is the master certificate set. They still // have yet to have their full certificate chains validated. Full signature checking is @@ -164,8 +159,8 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const for (Map< H384, SharedPtr< Entry > >::const_iterator c(m_bySerial.begin()); c != m_bySerial.end();) { if (c->second->error() == ZT_CERTIFICATE_ERROR_NONE) { const unsigned int uniqueIdSize = c->second->m_certificate.subject.uniqueIdSize; - if ((uniqueIdSize > 0) && (uniqueIdSize <= 1024)) { // 1024 is a sanity check value, actual unique IDs are <100 bytes - SharedPtr< Entry > ¤t = m_bySubjectUniqueId[Vector< uint8_t >(c->second->m_certificate.subject.uniqueId, c->second->m_certificate.subject.uniqueId + uniqueIdSize)]; + if ((uniqueIdSize > 0) && (uniqueIdSize <= ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE)) { + SharedPtr< Entry > ¤t = m_bySubjectUniqueId[Blob< ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE >(c->second->m_certificate.subject.uniqueId, uniqueIdSize)]; if (current) { exitLoop = false; if (c->second->m_certificate.subject.timestamp > current->m_certificate.subject.timestamp) { @@ -222,6 +217,8 @@ void TrustStore::update(const int64_t clock, Vector< SharedPtr< Entry > > *const } } } + + return true; } Vector< uint8_t > TrustStore::save() const diff --git a/core/TrustStore.hpp b/core/TrustStore.hpp index a4977d5ec..7a81eea4d 100644 --- a/core/TrustStore.hpp +++ b/core/TrustStore.hpp @@ -124,13 +124,6 @@ public: */ Vector< SharedPtr< Entry > > all(bool includeRejectedCertificates) const; - /** - * Get a copy of the current rejected certificate set. - * - * @return Rejected certificates - */ - Vector< SharedPtr< Entry > > rejects() const; - /** * Add a certificate * @@ -161,8 +154,9 @@ public: * * @param clock Current time in milliseconds since epoch, or -1 to not check times on this pass * @param purge If non-NULL, purge rejected certificates and return them in this vector (vector should be empty) + * @return True if there were changes */ - void update(int64_t clock, Vector< SharedPtr< Entry > > *purge); + bool update(int64_t clock, Vector< SharedPtr< Entry > > *purge); /** * Create a compressed binary version of certificates and their local trust @@ -184,7 +178,7 @@ public: private: Map< H384, SharedPtr< Entry > > m_bySerial; // all certificates - Map< Vector< uint8_t >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only + Map< Blob< ZT_CERTIFICATE_UNIQUE_ID_TYPE_NIST_P_384_SIZE >, SharedPtr< Entry > > m_bySubjectUniqueId; // non-rejected certificates only Map< Fingerprint, Vector< SharedPtr< Entry > > > m_bySubjectIdentity; // non-rejected certificates only ForwardList< SharedPtr< Entry > > m_addQueue; ForwardList< H384 > m_deleteQueue; diff --git a/core/Utils.cpp b/core/Utils.cpp index f104b2fb3..2811ee213 100644 --- a/core/Utils.cpp +++ b/core/Utils.cpp @@ -529,7 +529,7 @@ bool scopy(char *const dest, const unsigned int len, const char *const src) noex } } -uint32_t fnv1a32(const void *const data, const unsigned int len) noexcept +uint32_t fnv1a32(const void *const restrict data, const unsigned int len) noexcept { uint32_t h = 0x811c9dc5; const uint32_t p = 0x01000193; diff --git a/core/Utils.hpp b/core/Utils.hpp index 26e784c99..93af18e25 100644 --- a/core/Utils.hpp +++ b/core/Utils.hpp @@ -546,7 +546,7 @@ static ZT_INLINE I ntoh(const I n) noexcept * @return Loaded raw integer */ template< typename I > -static ZT_INLINE I loadMachineEndian(const void *const p) noexcept +static ZT_INLINE I loadMachineEndian(const void *const restrict p) noexcept { #ifdef ZT_NO_UNALIGNED_ACCESS I tmp; @@ -566,7 +566,7 @@ static ZT_INLINE I loadMachineEndian(const void *const p) noexcept * @param i Integer to store */ template< typename I > -static ZT_INLINE void storeMachineEndian(void *const p, const I i) noexcept +static ZT_INLINE void storeMachineEndian(void *const restrict p, const I i) noexcept { #ifdef ZT_NO_UNALIGNED_ACCESS for(unsigned int k=0;k -static ZT_INLINE I loadBigEndian(const void *const p) noexcept +static ZT_INLINE I loadBigEndian(const void *const restrict p) noexcept { #ifdef ZT_NO_UNALIGNED_ACCESS return _load_be_bysize::l(reinterpret_cast(p)); @@ -601,7 +601,7 @@ static ZT_INLINE I loadBigEndian(const void *const p) noexcept * #param i Integer to write */ template< typename I > -static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept +static ZT_INLINE void storeBigEndian(void *const restrict p, I i) noexcept { #ifdef ZT_NO_UNALIGNED_ACCESS storeMachineEndian(p,hton(i)); @@ -618,7 +618,7 @@ static ZT_INLINE void storeBigEndian(void *const p, I i) noexcept * @return Decoded integer */ template< typename I > -static ZT_INLINE I loadLittleEndian(const void *const p) noexcept +static ZT_INLINE I loadLittleEndian(const void *const restrict p) noexcept { #if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS) return _load_le_bysize::l(reinterpret_cast(p)); @@ -635,7 +635,7 @@ static ZT_INLINE I loadLittleEndian(const void *const p) noexcept * #param i Integer to write */ template< typename I > -static ZT_INLINE void storeLittleEndian(void *const p, const I i) noexcept +static ZT_INLINE void storeLittleEndian(void *const restrict p, const I i) noexcept { #if __BYTE_ORDER == __BIG_ENDIAN storeMachineEndian(p,_swap_bytes_bysize::s(i)); @@ -723,7 +723,7 @@ static ZT_INLINE void zero(void *dest, unsigned long len) noexcept * @param len Length of data * @return FNV1a checksum */ -uint32_t fnv1a32(const void *data, unsigned int len) noexcept; +uint32_t fnv1a32(const void *restrict data, unsigned int len) noexcept; /** * Mix bits in a 64-bit integer (non-cryptographic, for hash tables) diff --git a/core/VL1.cpp b/core/VL1.cpp index f162a1514..1138d09b4 100644 --- a/core/VL1.cpp +++ b/core/VL1.cpp @@ -99,13 +99,12 @@ VL1::VL1(const RuntimeEnvironment *renv) : RR(renv) {} -void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept +void VL1::onRemotePacket(CallContext &cc, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, const unsigned int len) noexcept { const SharedPtr< Path > path(RR->topology->path(localSocket, fromAddr)); - const int64_t now = RR->node->now(); ZT_SPEW("%u bytes from %s (local socket %lld)", len, fromAddr.toString().c_str(), localSocket); - path->received(now, len); + path->received(cc, len); // NOTE: likely/unlikely are used here to highlight the most common code path // for valid data packets. This may allow the compiler to generate very slightly @@ -121,7 +120,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); const Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX); if (destination != RR->identity.address()) { - m_relay(tPtr, path, destination, data, len); + m_relay(cc, path, destination, data, len); return; } @@ -145,7 +144,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet len - ZT_PROTO_PACKET_FRAGMENT_PAYLOAD_START_AT, fragmentNo, totalFragments, - now, + cc.ticks, path)) { case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE: break; @@ -171,7 +170,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet len, 0, // always the zero'eth fragment 0, // this is specified in fragments, not in the head - now, + cc.ticks, path)) { case Defragmenter< ZT_MAX_PACKET_FRAGMENTS >::COMPLETE: break; @@ -214,9 +213,9 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); return; } - const SharedPtr< Peer > peer(m_HELLO(tPtr, path, *pkt, pktSize)); + const SharedPtr< Peer > peer(m_HELLO(cc, path, *pkt, pktSize)); if (likely(peer)) - peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP); + peer->received(cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP); return; } @@ -225,7 +224,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet // secrecy status. unsigned int auth = 0; - SharedPtr< Peer > peer(RR->topology->peer(tPtr, source)); + SharedPtr< Peer > peer(RR->topology->peer(cc, source)); if (likely(peer)) { switch (cipher) { @@ -245,7 +244,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); - RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return; } @@ -269,7 +268,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); if (unlikely(Utils::loadMachineEndian< uint64_t >(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); - RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return; } @@ -288,7 +287,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet break; default: - RR->t->incomingPacketDropped(tPtr, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return; } } @@ -327,7 +326,7 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet ZT_SPEW("decompressed packet: %d -> %d", pktSize, ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen); pktSize = ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen; } else { - RR->t->incomingPacketDropped(tPtr, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA); + RR->t->incomingPacketDropped(cc, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA); return; } } @@ -345,66 +344,66 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet case Protocol::VERB_NOP: break; case Protocol::VERB_HELLO: - ok = (bool)(m_HELLO(tPtr, path, *pkt, pktSize)); + ok = (bool)(m_HELLO(cc, path, *pkt, pktSize)); break; case Protocol::VERB_ERROR: - ok = m_ERROR(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); + ok = m_ERROR(cc, packetId, auth, path, peer, *pkt, pktSize, inReVerb); break; case Protocol::VERB_OK: - ok = m_OK(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); + ok = m_OK(cc, packetId, auth, path, peer, *pkt, pktSize, inReVerb); break; case Protocol::VERB_WHOIS: - ok = m_WHOIS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_WHOIS(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_RENDEZVOUS: - ok = m_RENDEZVOUS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_RENDEZVOUS(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_FRAME: - ok = RR->vl2->m_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_FRAME(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_EXT_FRAME: - ok = RR->vl2->m_EXT_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_EXT_FRAME(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_ECHO: - ok = m_ECHO(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_ECHO(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_MULTICAST_LIKE: - ok = RR->vl2->m_MULTICAST_LIKE(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_MULTICAST_LIKE(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_NETWORK_CREDENTIALS: - ok = RR->vl2->m_NETWORK_CREDENTIALS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_NETWORK_CREDENTIALS(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_NETWORK_CONFIG_REQUEST: - ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_NETWORK_CONFIG: - ok = RR->vl2->m_NETWORK_CONFIG(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_NETWORK_CONFIG(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_MULTICAST_GATHER: - ok = RR->vl2->m_MULTICAST_GATHER(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_MULTICAST_GATHER(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_MULTICAST_FRAME_deprecated: - ok = RR->vl2->m_MULTICAST_FRAME_deprecated(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_MULTICAST_FRAME_deprecated(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_PUSH_DIRECT_PATHS: - ok = m_PUSH_DIRECT_PATHS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_PUSH_DIRECT_PATHS(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_USER_MESSAGE: - ok = m_USER_MESSAGE(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_USER_MESSAGE(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_MULTICAST: - ok = RR->vl2->m_MULTICAST(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = RR->vl2->m_MULTICAST(cc, packetId, auth, path, peer, *pkt, pktSize); break; case Protocol::VERB_ENCAP: - ok = m_ENCAP(tPtr, packetId, auth, path, peer, *pkt, pktSize); + ok = m_ENCAP(cc, packetId, auth, path, peer, *pkt, pktSize); break; default: - RR->t->incomingPacketDropped(tPtr, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); + RR->t->incomingPacketDropped(cc, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); break; } if (likely(ok)) - peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb); + peer->received(cc, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb); } else { // If decryption and authentication were not successful, try to look up identities. // This is rate limited by virtue of the retry rate limit timer. @@ -419,27 +418,27 @@ void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const Inet const unsigned int wpidx = wq.waitingPacketCount++ % ZT_VL1_MAX_WHOIS_WAITING_PACKETS; wq.waitingPacketSize[wpidx] = (unsigned int)pktSize; wq.waitingPacket[wpidx] = pkt; - sendPending = (now - wq.lastRetry) >= ZT_WHOIS_RETRY_DELAY; + sendPending = (cc.ticks - wq.lastRetry) >= ZT_WHOIS_RETRY_DELAY; } if (sendPending) - m_sendPendingWhois(tPtr, now); + m_sendPendingWhois(cc); } } } catch (...) { - RR->t->unexpectedError(tPtr, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str()); + RR->t->unexpectedError(cc, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str()); } } -void VL1::m_relay(void *tPtr, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize) +void VL1::m_relay(CallContext &cc, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize) { } -void VL1::m_sendPendingWhois(void *tPtr, int64_t now) +void VL1::m_sendPendingWhois(CallContext &cc) { const SharedPtr< Peer > root(RR->topology->root()); if (unlikely(!root)) return; - const SharedPtr< Path > rootPath(root->path(now)); + const SharedPtr< Path > rootPath(root->path(cc)); if (unlikely(!rootPath)) return; @@ -447,8 +446,8 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now) { Mutex::Lock wl(m_whoisQueue_l); for (Map< Address, p_WhoisQueueItem >::iterator wi(m_whoisQueue.begin()); wi != m_whoisQueue.end(); ++wi) { - if ((now - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) { - wi->second.lastRetry = now; + if ((cc.ticks - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) { + wi->second.lastRetry = cc.ticks; ++wi->second.retries; toSend.push_back(wi->first); } @@ -468,13 +467,13 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now) p += ZT_ADDRESS_LENGTH; } Protocol::armor(outp, p, key, root->cipher()); - RR->expect->sending(packetId, now); - root->send(tPtr, now, outp, p, rootPath); + RR->expect->sending(packetId, cc.ticks); + root->send(cc, outp, p, rootPath); } } } -SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &pkt, int packetSize) +SharedPtr< Peer > VL1::m_HELLO(CallContext &cc, const SharedPtr< Path > &path, Buf &pkt, int packetSize) { const uint64_t packetId = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_ID_INDEX); const uint64_t mac = Utils::loadMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX); @@ -482,7 +481,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p const uint8_t protoVersion = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START >(); if (unlikely(protoVersion < ZT_PROTO_VERSION_MIN)) { - RR->t->incomingPacketDropped(tPtr, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); + RR->t->incomingPacketDropped(cc, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); return SharedPtr< Peer >(); } const unsigned int versionMajor = pkt.lI8< ZT_PROTO_PACKET_PAYLOAD_START + 1 >(); @@ -495,19 +494,19 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p // Get identity and verify that it matches the sending address in the packet. Identity id; if (unlikely(pkt.rO(ii, id) < 0)) { - RR->t->incomingPacketDropped(tPtr, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr< Peer >(); } if (unlikely(id.address() != Address(pkt.unsafeData + ZT_PROTO_PACKET_SOURCE_INDEX))) { - RR->t->incomingPacketDropped(tPtr, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } // Get the peer that matches this identity, or learn a new one if we don't know it. - SharedPtr< Peer > peer(RR->topology->peer(tPtr, id.address(), true)); + SharedPtr< Peer > peer(RR->topology->peer(cc, id.address(), true)); if (peer) { if (unlikely(peer->identity() != id)) { - RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } if (unlikely(peer->deduplicateIncomingPacket(packetId))) { @@ -516,15 +515,15 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p } } else { if (unlikely(!id.locallyValidate())) { - RR->t->incomingPacketDropped(tPtr, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr< Peer >(); } peer.set(new Peer(RR)); - if (unlikely(!peer->init(id))) { - RR->t->incomingPacketDropped(tPtr, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED); + if (unlikely(!peer->init(cc, id))) { + RR->t->incomingPacketDropped(cc, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED); return SharedPtr< Peer >(); } - peer = RR->topology->add(tPtr, peer); + peer = RR->topology->add(cc, peer); } // ------------------------------------------------------------------------------------------------------------------ @@ -537,7 +536,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p // field is ignored, and eventually it'll be undefined. uint8_t hmac[ZT_HMACSHA384_LEN]; if (unlikely(packetSize < ZT_HMACSHA384_LEN)) { - RR->t->incomingPacketDropped(tPtr, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } packetSize -= ZT_HMACSHA384_LEN; @@ -545,7 +544,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p Utils::storeMachineEndian< uint64_t >(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0 HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac); if (unlikely(!Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) { - RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } } else { @@ -560,11 +559,11 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p uint64_t polyMac[2]; poly1305.finish(polyMac); if (unlikely(mac != polyMac[0])) { - RR->t->incomingPacketDropped(tPtr, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } } else { - RR->t->incomingPacketDropped(tPtr, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(cc, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr< Peer >(); } } @@ -575,7 +574,7 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p InetAddress sentTo; if (unlikely(pkt.rO(ii, sentTo) < 0)) { - RR->t->incomingPacketDropped(tPtr, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr< Peer >(); } @@ -595,12 +594,12 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p ii += 2; // skip reserved field const unsigned int dictSize = pkt.rI16(ii); if (unlikely((ii + dictSize) > packetSize)) { - RR->t->incomingPacketDropped(tPtr, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return peer; } Dictionary md; if (!md.decode(pkt.unsafeData + ii, dictSize)) { - RR->t->incomingPacketDropped(tPtr, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(cc, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return peer; } @@ -635,11 +634,11 @@ SharedPtr< Peer > VL1::m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &p } peer->setRemoteVersion(protoVersion, versionMajor, versionMinor, versionRev); - peer->send(tPtr, RR->node->now(), pkt.unsafeData, ii, path); + peer->send(cc, pkt.unsafeData, ii, path); return peer; } -bool VL1::m_ERROR(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) +bool VL1::m_ERROR(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { #if 0 if (packetSize < (int)sizeof(Protocol::ERROR::Header)) { @@ -686,20 +685,19 @@ bool VL1::m_ERROR(void *tPtr, const uint64_t packetId, const unsigned int auth, #endif } -bool VL1::m_OK(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) +bool VL1::m_OK(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { int ii = ZT_PROTO_PACKET_PAYLOAD_START + 13; inReVerb = (Protocol::Verb)pkt.rI8(ii); const uint64_t inRePacketId = pkt.rI64(ii); if (unlikely(Buf::readOverflow(ii, packetSize))) { - RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); + RR->t->incomingPacketDropped(cc, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); return false; } - const int64_t now = RR->node->now(); - if (unlikely(!RR->expect->expecting(inRePacketId, now))) { - RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED); + if (unlikely(!RR->expect->expecting(inRePacketId, cc.ticks))) { + RR->t->incomingPacketDropped(cc, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED); return false; } @@ -724,7 +722,7 @@ bool VL1::m_OK(void *tPtr, const uint64_t packetId, const unsigned int auth, con return true; } -bool VL1::m_WHOIS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_WHOIS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { #if 0 if (packetSize < (int)sizeof(Protocol::OK::Header)) { @@ -778,7 +776,7 @@ bool VL1::m_WHOIS(void *tPtr, const uint64_t packetId, const unsigned int auth, #endif } -bool VL1::m_RENDEZVOUS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_RENDEZVOUS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { #if 0 if (RR->topology->isRoot(peer->identity())) { @@ -826,7 +824,7 @@ bool VL1::m_RENDEZVOUS(void *tPtr, const uint64_t packetId, const unsigned int a #endif } -bool VL1::m_ECHO(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_ECHO(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { #if 0 const uint64_t packetId = Protocol::packetId(pkt,packetSize); @@ -864,7 +862,7 @@ bool VL1::m_ECHO(void *tPtr, const uint64_t packetId, const unsigned int auth, c #endif } -bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_PUSH_DIRECT_PATHS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { #if 0 if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) { @@ -955,13 +953,13 @@ bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const uint64_t packetId, const unsigne #endif } -bool VL1::m_USER_MESSAGE(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_USER_MESSAGE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { // TODO return true; } -bool VL1::m_ENCAP(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL1::m_ENCAP(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { // TODO: not implemented yet return true; diff --git a/core/VL1.hpp b/core/VL1.hpp index cd5103149..99b54d6db 100644 --- a/core/VL1.hpp +++ b/core/VL1.hpp @@ -22,6 +22,7 @@ #include "Mutex.hpp" #include "FCV.hpp" #include "Containers.hpp" +#include "CallContext.hpp" #define ZT_VL1_MAX_WHOIS_WAITING_PACKETS 32 @@ -56,38 +57,37 @@ public: * contents should not be used after this call. Make a copy if the * data might still be needed. * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param localSocket Local I/O socket as supplied by external code * @param fromAddr Internet IP address of origin * @param data Packet data * @param len Packet length */ - void onRemotePacket(void *tPtr, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept; + void onRemotePacket(CallContext &cc, int64_t localSocket, const InetAddress &fromAddr, SharedPtr< Buf > &data, unsigned int len) noexcept; private: const RuntimeEnvironment *RR; - void m_relay(void *tPtr, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize); + void m_relay(CallContext &cc, const SharedPtr< Path > &path, Address destination, SharedPtr< Buf > &pkt, int pktSize); - void m_sendPendingWhois(void *tPtr, int64_t now); + void m_sendPendingWhois(CallContext &cc); - SharedPtr< Peer > m_HELLO(void *tPtr, const SharedPtr< Path > &path, Buf &pkt, int packetSize); + SharedPtr< Peer > m_HELLO(CallContext &cc, const SharedPtr< Path > &path, Buf &pkt, int packetSize); - bool m_ERROR(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); + bool m_ERROR(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); - bool m_OK(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); + bool m_OK(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb); - bool m_WHOIS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_WHOIS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_RENDEZVOUS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_RENDEZVOUS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_ECHO(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_ECHO(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_PUSH_DIRECT_PATHS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_PUSH_DIRECT_PATHS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_USER_MESSAGE(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_USER_MESSAGE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_ENCAP(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_ENCAP(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, const SharedPtr< Peer > &peer, Buf &pkt, int packetSize); // Defragmentation engine for handling inbound packets with more than one fragment. Defragmenter< ZT_MAX_PACKET_FRAGMENTS > m_inputPacketAssembler; diff --git a/core/VL2.cpp b/core/VL2.cpp index 7e5d1e15e..a4c42fc93 100644 --- a/core/VL2.cpp +++ b/core/VL2.cpp @@ -26,43 +26,43 @@ VL2::VL2(const RuntimeEnvironment *renv) { } -void VL2::onLocalEthernet(void *const tPtr, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len) +void VL2::onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, const unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len) { } -bool VL2::m_FRAME(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_EXT_FRAME(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_EXT_FRAME(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_MULTICAST_LIKE(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_MULTICAST_LIKE(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_NETWORK_CREDENTIALS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_NETWORK_CREDENTIALS(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_NETWORK_CONFIG_REQUEST(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_NETWORK_CONFIG_REQUEST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_NETWORK_CONFIG(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_NETWORK_CONFIG(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_MULTICAST_GATHER(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_MULTICAST_GATHER(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_MULTICAST_FRAME_deprecated(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_MULTICAST_FRAME_deprecated(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } -bool VL2::m_MULTICAST(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) +bool VL2::m_MULTICAST(CallContext &cc, const uint64_t packetId, const unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize) { } diff --git a/core/VL2.hpp b/core/VL2.hpp index 3cd83e011..f58ef16df 100644 --- a/core/VL2.hpp +++ b/core/VL2.hpp @@ -21,6 +21,7 @@ #include "Mutex.hpp" #include "FCV.hpp" #include "Containers.hpp" +#include "CallContext.hpp" namespace ZeroTier { @@ -46,7 +47,6 @@ public: /** * Called when a packet comes from a local Ethernet tap * - * @param tPtr Thread pointer to be handed through to any callbacks called as a result of this call * @param network Which network's TAP did this packet come from? * @param from Originating MAC address * @param to Destination MAC address @@ -55,26 +55,26 @@ public: * @param data Ethernet payload * @param len Frame length */ - void onLocalEthernet(void *tPtr, const SharedPtr< Network > &network, const MAC &from, const MAC &to, unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len); + void onLocalEthernet(CallContext &cc, const SharedPtr< Network > &network, const MAC &from, const MAC &to, unsigned int etherType, unsigned int vlanId, SharedPtr< Buf > &data, unsigned int len); protected: - bool m_FRAME(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_EXT_FRAME(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_EXT_FRAME(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_MULTICAST_LIKE(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_LIKE(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_NETWORK_CREDENTIALS(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CREDENTIALS(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_NETWORK_CONFIG_REQUEST(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CONFIG_REQUEST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_NETWORK_CONFIG(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_NETWORK_CONFIG(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_MULTICAST_GATHER(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_GATHER(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_MULTICAST_FRAME_deprecated(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_MULTICAST_FRAME_deprecated(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); - bool m_MULTICAST(void *tPtr, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); + bool m_MULTICAST(CallContext &cc, uint64_t packetId, unsigned int auth, const SharedPtr< Path > &path, SharedPtr< Peer > &peer, Buf &pkt, int packetSize); private: }; diff --git a/core/zerotier.h b/core/zerotier.h index 26407d48c..e0e960291 100644 --- a/core/zerotier.h +++ b/core/zerotier.h @@ -1750,18 +1750,10 @@ enum ZT_StateObjectType * List of certificates, their local trust, and locally added roots * * Object ID: (none) - * Canonical path: /trust + * Canonical path: /truststore * Persistence: required if root settings should persist */ - ZT_STATE_OBJECT_TRUST_STORE = 7, - - /** - * Certificate - * - * Object ID: [6]serial (384-bit serial packed into 6 uint64_t's) - * Canonical path: /certs.d/ (96-digit hex serial) - */ - ZT_STATE_OBJECT_CERT = 8 + ZT_STATE_OBJECT_TRUST_STORE = 7 }; /** @@ -2028,7 +2020,7 @@ struct ZT_Node_Callbacks * * @return Pointer to I/O buffer */ -ZT_SDK_API void *ZT_getBuffer(); +ZT_SDK_API [[maybe_unused]] void *ZT_getBuffer(); /** * Free an unused buffer obtained via getBuffer @@ -2059,37 +2051,32 @@ ZT_SDK_API void ZT_freeQueryResult(const void *qr); * * @param node Result: pointer is set to new node instance on success * @param uptr User pointer to pass to functions/callbacks - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param callbacks Callback function configuration - * @param now Current clock in milliseconds * @return OK (0) or error code if a fatal error condition has occurred */ ZT_SDK_API enum ZT_ResultCode ZT_Node_new( ZT_Node **node, - void *uptr, + int64_t clock, + int64_t ticks, void *tptr, - const struct ZT_Node_Callbacks *callbacks, - int64_t now); + void *uptr, + const struct ZT_Node_Callbacks *callbacks); /** * Delete a node and free all resources it consumes * * If you are using multiple threads, all other threads must be shut down * first. This can crash if processXXX() methods are in progress. - * - * @param node Node to delete - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call */ ZT_SDK_API void ZT_Node_delete( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr); /** * Process a packet received from the physical wire * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param now Current clock in milliseconds * @param localSocket Local socket (you can use 0 if only one local socket is bound and ignore this) * @param remoteAddress Origin of packet * @param packetData Packet data @@ -2100,8 +2087,9 @@ ZT_SDK_API void ZT_Node_delete( */ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, int64_t localSocket, const ZT_InetAddress *remoteAddress, const void *packetData, @@ -2112,9 +2100,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( /** * Process a frame from a virtual network port (tap) * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param now Current clock in milliseconds * @param nwid ZeroTier 64-bit virtual network ID * @param sourceMac Source MAC address (least significant 48 bits) * @param destMac Destination MAC address (least significant 48 bits) @@ -2128,8 +2113,9 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processWirePacket( */ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, uint64_t nwid, uint64_t sourceMac, uint64_t destMac, @@ -2143,16 +2129,15 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processVirtualNetworkFrame( /** * Perform periodic background operations * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param now Current clock in milliseconds * @param nextBackgroundTaskDeadline Value/result: set to deadline for next call to processBackgroundTasks() * @return OK (0) or error code if a fatal error condition has occurred */ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, volatile int64_t *nextBackgroundTaskDeadline); /** @@ -2164,19 +2149,18 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_processBackgroundTasks( * If we are already a member of the network, nothing is done and OK is * returned. * - * @param node Node instance * @param nwid 64-bit ZeroTier network ID * @param fingerprintHash If non-NULL this is the full fingerprint of the controller - * @param uptr An arbitrary pointer to associate with this network (default: NULL) - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @return OK (0) or error code if a fatal error condition has occurred */ ZT_SDK_API enum ZT_ResultCode ZT_Node_join( ZT_Node *node, - uint64_t nwid, - const ZT_Fingerprint *controllerFingerprint, + int64_t clock, + int64_t ticks, + void *tptr, void *uptr, - void *tptr); + uint64_t nwid, + const ZT_Fingerprint *controllerFingerprint); /** * Leave a network @@ -2188,17 +2172,15 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_join( * The uptr parameter is optional and is NULL by default. If it is not NULL, * the pointer it points to is set to this network's uptr on success. * - * @param node Node instance - * @param nwid 64-bit network ID - * @param uptr Target pointer is set to uptr (if not NULL) - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @return OK (0) or error code if a fatal error condition has occurred */ ZT_SDK_API enum ZT_ResultCode ZT_Node_leave( ZT_Node *node, - uint64_t nwid, + int64_t clock, + int64_t ticks, + void *tptr, void **uptr, - void *tptr); + uint64_t nwid); /** * Subscribe to an Ethernet multicast group @@ -2219,8 +2201,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_leave( * * This does not generate an update call to networkConfigCallback(). * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call * @param nwid 64-bit network ID * @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits) * @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed) @@ -2228,6 +2208,8 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_leave( */ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, uint64_t nwid, uint64_t multicastGroup, @@ -2241,7 +2223,6 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe( * * This does not generate an update call to networkConfigCallback(). * - * @param node Node instance * @param nwid 64-bit network ID * @param multicastGroup Ethernet multicast or broadcast MAC (least significant 48 bits) * @param multicastAdi Multicast ADI (least significant 32 bits only, use 0 if not needed) @@ -2249,6 +2230,9 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastSubscribe( */ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe( ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, uint64_t nwid, uint64_t multicastGroup, unsigned long multicastAdi); @@ -2256,10 +2240,10 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_multicastUnsubscribe( /** * Get this node's 40-bit ZeroTier address * - * @param node Node instance * @return ZeroTier address (least significant 40 bits of 64-bit int) */ -ZT_SDK_API uint64_t ZT_Node_address(ZT_Node *node); +ZT_SDK_API uint64_t ZT_Node_address( + ZT_Node *node); /** * Get this node's identity @@ -2267,19 +2251,21 @@ ZT_SDK_API uint64_t ZT_Node_address(ZT_Node *node); * The identity pointer returned by this function need not and should not be * freed with ZT_Identity_delete(). It's valid until the node is deleted. * - * @param node Node instance * @return Identity */ -ZT_SDK_API const ZT_Identity *ZT_Node_identity(ZT_Node *node); +ZT_SDK_API const ZT_Identity *ZT_Node_identity( + ZT_Node *node); /** * Get the status of this node * - * @param node Node instance * @param status Buffer to fill with current node status */ ZT_SDK_API void ZT_Node_status( ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, ZT_NodeStatus *status); /** @@ -2288,10 +2274,13 @@ ZT_SDK_API void ZT_Node_status( * The pointer returned here must be freed with freeQueryResult() * when you are done with it. * - * @param node Node instance * @return List of known peers or NULL on failure */ -ZT_SDK_API ZT_PeerList *ZT_Node_peers(ZT_Node *node); +ZT_SDK_API ZT_PeerList *ZT_Node_peers( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr); /** * Get the status of a virtual network @@ -2299,12 +2288,14 @@ ZT_SDK_API ZT_PeerList *ZT_Node_peers(ZT_Node *node); * The pointer returned here must be freed with freeQueryResult() * when you are done with it. * - * @param node Node instance * @param nwid 64-bit network ID * @return Network configuration or NULL if we are not a member of this network */ ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig( ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, uint64_t nwid); /** @@ -2313,7 +2304,8 @@ ZT_SDK_API ZT_VirtualNetworkConfig *ZT_Node_networkConfig( * @param node Node instance * @return List of networks or NULL on failure */ -ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks(ZT_Node *node); +ZT_SDK_API ZT_VirtualNetworkList *ZT_Node_networks( + ZT_Node *node); /** * Set the network-associated user-defined pointer for a given network @@ -2338,61 +2330,18 @@ ZT_SDK_API void ZT_Node_setNetworkUserPtr( */ ZT_SDK_API void ZT_Node_setInterfaceAddresses( ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr, const ZT_InterfaceAddress *addrs, unsigned int addrCount); -/** - * Add a peer directly by supplying its identity - * - * This does not authorize the peer on a network (only the network's - * controller can do that) or otherwise give it special privileges. It - * also doesn't guarantee it will be contacted. It just adds it to the - * internal peer data set if it is not already present. - * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param id Identity of peer to add - * @return OK (0) or error code - */ -ZT_SDK_API enum ZT_ResultCode ZT_Node_addPeer( - ZT_Node *node, - void *tptr, - const ZT_Identity *id); - -/** - * Attempt to contact a peer at an explicit endpoint address. - * - * If the fingerprint structure's hash is all zeroes, the peer is - * looked up only by address. - * - * This can only fail if the peer was not found. - * - * Note that this can immediately (before this returns) result in - * calls to the send packet functions supplied to the core. - * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param fp Fingerprint (or only address) - * @param endpoint Endpoint - * @param retries If greater than zero, try this many times - * @return Boolean: non-zero on success, zero if peer was not found - */ -ZT_SDK_API int ZT_Node_tryPeer( - ZT_Node *node, - void *tptr, - const ZT_Fingerprint *fp, - const ZT_Endpoint *endpoint, - int retries); - /** * Add a certificate to this node's certificate store * * This supports adding of certificates as expanded ZT_Certificate structures * or as raw data. If 'cert' is NULL then certData/certSize must be set. * - * @param node Node instance - * @param tptr Thread pointer to pass to functions/callbacks resulting from this call - * @param now Current time * @param localTrust Local trust flags (ORed together) * @param cert Certificate object, or set to NULL if certData and certSize are to be used * @param certData Certificate binary data if 'cert' is NULL, NULL otherwise @@ -2401,8 +2350,9 @@ ZT_SDK_API int ZT_Node_tryPeer( */ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, - int64_t now, unsigned int localTrust, const ZT_Certificate *cert, const void *certData, @@ -2421,6 +2371,8 @@ ZT_SDK_API enum ZT_CertificateError ZT_Node_addCertificate( */ ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, const void *serialNo); @@ -2430,7 +2382,11 @@ ZT_SDK_API enum ZT_ResultCode ZT_Node_deleteCertificate( * @param node Node instance * @return List of certificates or NULL on error */ -ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node); +ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates( + ZT_Node *node, + int64_t clock, + int64_t ticks, + void *tptr); /** * Send a VERB_USER_MESSAGE to another ZeroTier node @@ -2448,6 +2404,8 @@ ZT_SDK_API ZT_CertificateList *ZT_Node_listCertificates(ZT_Node *node); */ ZT_SDK_API int ZT_Node_sendUserMessage( ZT_Node *node, + int64_t clock, + int64_t ticks, void *tptr, uint64_t dest, uint64_t typeId, @@ -2665,7 +2623,7 @@ ZT_SDK_API int ZT_Endpoint_fromBytes( * Note that attributes must be either NULL to use defaults for all or there * must be an attributes object for each endpoint. * - * @param ts Locator timestamp + * @param rev Locator timestamp * @param endpoints List of endpoints to store in locator * @param endpointAttributes Array of ZT_EndpointAttributes objects or NULL to use defaults * @param endpointCount Number of endpoints (maximum: 8) @@ -2673,7 +2631,7 @@ ZT_SDK_API int ZT_Endpoint_fromBytes( * @return Locator or NULL on error (too many endpoints or identity does not have private key) */ ZT_SDK_API ZT_Locator *ZT_Locator_create( - int64_t ts, + int64_t rev, const ZT_Endpoint *endpoints, const ZT_EndpointAttributes *endpointAttributes, unsigned int endpointCount, @@ -2735,12 +2693,12 @@ ZT_SDK_API char *ZT_Locator_toString( ZT_SDK_API const ZT_Fingerprint *ZT_Locator_fingerprint(const ZT_Locator *loc); /** - * Get a locator's timestamp + * Get a locator's revision * * @param loc Locator to query - * @return Locator timestamp in milliseconds since epoch + * @return Locator revision */ -ZT_SDK_API int64_t ZT_Locator_timestamp(const ZT_Locator *loc); +ZT_SDK_API int64_t ZT_Locator_revision(const ZT_Locator *loc); /** * Get the number of endpoints in this locator diff --git a/rust-zerotier-core/src/locator.rs b/rust-zerotier-core/src/locator.rs index 353284bc8..34ff35c45 100644 --- a/rust-zerotier-core/src/locator.rs +++ b/rust-zerotier-core/src/locator.rs @@ -27,13 +27,13 @@ pub struct Locator { impl Locator { /// Create and sign a new locator. /// The signer must include its secret key. - pub fn new(signer: &Identity, timestamp: i64, endpoints: &Vec) -> Result { + pub fn new(signer: &Identity, revision: i64, endpoints: &Vec) -> Result { let mut capi_endpoints: Vec = Vec::new(); capi_endpoints.reserve(endpoints.len()); for ep in endpoints.iter() { capi_endpoints.push(ep.capi); } - let loc = unsafe { ztcore::ZT_Locator_create(timestamp, capi_endpoints.as_ptr(), null(), capi_endpoints.len() as c_uint, signer.capi) }; + let loc = unsafe { ztcore::ZT_Locator_create(revision, capi_endpoints.as_ptr(), null(), capi_endpoints.len() as c_uint, signer.capi) }; if loc.is_null() { Err(ResultCode::ErrorBadParameter) } else { @@ -65,9 +65,9 @@ impl Locator { } #[inline(always)] - pub fn timestamp(&self) -> i64 { + pub fn revision(&self) -> i64 { unsafe { - ztcore::ZT_Locator_timestamp(self.capi) as i64 + ztcore::ZT_Locator_revision(self.capi) as i64 } } diff --git a/rust-zerotier-core/src/node.rs b/rust-zerotier-core/src/node.rs index bbace933a..3fe68818c 100644 --- a/rust-zerotier-core/src/node.rs +++ b/rust-zerotier-core/src/node.rs @@ -48,7 +48,14 @@ pub enum StateObjectType { Peer = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_PEER as isize, NetworkConfig = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_NETWORK_CONFIG as isize, TrustStore = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_TRUST_STORE as isize, - Certificate = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_CERT as isize, +} + +impl StateObjectType { + /// True if this state object should be protected. + #[inline(always)] + pub fn is_secret(&self) -> bool { + *self == StateObjectType::IdentitySecret || *self == StateObjectType::TrustStore + } } /// The status of a ZeroTier node. diff --git a/service/src/store.rs b/service/src/store.rs index 52124381e..815de4371 100644 --- a/service/src/store.rs +++ b/service/src/store.rs @@ -35,7 +35,6 @@ pub(crate) struct Store { peers_path: Box, controller_path: Box, networks_path: Box, - certs_path: Box, auth_token_path: Mutex>, auth_token: Mutex, } @@ -69,7 +68,6 @@ impl Store { peers_path: bp.join("peers.d").into_boxed_path(), controller_path: bp.join("controller.d").into_boxed_path(), networks_path: bp.join("networks.d").into_boxed_path(), - certs_path: bp.join("certs.d").into_boxed_path(), auth_token_path: Mutex::new(auth_token_path_override.map_or_else(|| { bp.join(AUTHTOKEN_SECRET).into_boxed_path() }, |auth_token_path_override| { @@ -85,32 +83,16 @@ impl Store { let _ = std::fs::create_dir_all(&s.peers_path); let _ = std::fs::create_dir_all(&s.controller_path); let _ = std::fs::create_dir_all(&s.networks_path); - let _ = std::fs::create_dir_all(&s.certs_path); Ok(s) } fn make_obj_path_internal(&self, obj_type: &StateObjectType, obj_id: &[u64]) -> Option { match obj_type { - StateObjectType::IdentityPublic => { - Some(self.base_path.join("identity.public")) - }, - StateObjectType::IdentitySecret => { - Some(self.base_path.join("identity.secret")) - }, - StateObjectType::Certificate => { - if obj_id.len() < 6 { - None - } else { - Some(self.certs_path.join(format!("{:0>16x}{:0>16x}{:0>16x}{:0>16x}{:0>16x}{:0>16x}.cert", obj_id[0], obj_id[1], obj_id[2], obj_id[3], obj_id[4], obj_id[5]))) - } - }, - StateObjectType::TrustStore => { - Some(self.base_path.join("trust")) - }, - StateObjectType::Locator => { - Some(self.base_path.join("locator")) - }, + StateObjectType::IdentityPublic => Some(self.base_path.join("identity.public")), + StateObjectType::IdentitySecret => Some(self.base_path.join("identity.secret")), + StateObjectType::TrustStore => Some(self.base_path.join("truststore")), + StateObjectType::Locator => Some(self.base_path.join("locator")), StateObjectType::NetworkConfig => { if obj_id.len() < 1 { None @@ -306,7 +288,7 @@ impl Store { let obj_path = obj_path.unwrap(); std::fs::OpenOptions::new().write(true).truncate(true).create(true).open(&obj_path)?.write_all(obj_data)?; - if obj_type.eq(&StateObjectType::IdentitySecret) || obj_type.eq(&StateObjectType::TrustStore) { + if obj_type.is_secret() { lock_down_file(obj_path.to_str().unwrap()); }