A bunch more build fixes.

This commit is contained in:
Adam Ierymenko 2020-02-21 14:46:01 -08:00
parent 1a2378a3d4
commit 55b0555aa0
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
14 changed files with 207 additions and 191 deletions

View file

@ -7,13 +7,16 @@ else()
cmake_policy(VERSION 3.15)
endif()
set(CMAKE_CXX_STANDARD 11)
set(default_build_type "Release")
if(WIN32)
set(CMAKE_SYSTEM_VERSION "7" CACHE STRING INTERNAL FORCE)
endif(WIN32)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.9" CACHE STRING "Minimum OS X Deployment Version")
set(ZEROTIER_ONE_VERSION_MAJOR 2 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_MINOR 0 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_MAJOR 1 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_MINOR 9 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_REVISION 0 CACHE INTERNAL "")
set(ZEROTIER_ONE_VERSION_BUILD 0 CACHE INTERNAL "")
@ -22,11 +25,6 @@ configure_file(
${CMAKE_BINARY_DIR}/version.h
)
set(default_build_type "Release")
#if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
# set(default_build_type "Debug")
#endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
@ -54,7 +52,6 @@ if(WIN32)
add_definitions(-DNOMINMAX)
else(WIN32)
if(APPLE)
message("++ Setting MacOS Compiler Flags ${CMAKE_BUILD_TYPE}")
add_compile_options(
-Wall
@ -74,9 +71,7 @@ else(WIN32)
-mmacosx-version-min=10.9
$<$<CONFIG:RELEASE>:-flto>
)
else(APPLE)
message("++ Setting Linux/BSD/Posix Compiler Flags (${CMAKE_BUILD_TYPE})")
add_compile_options(
-Wall
@ -90,7 +85,6 @@ else(WIN32)
$<$<CONFIG:RELWITHDEBINFO>:-fPIE>
$<$<CONFIG:RELWITHDEBINFO>:-g>
)
endif(APPLE)
endif(WIN32)
@ -103,19 +97,7 @@ if (
CMAKE_SYSTEM_PROCESSOR MATCHES "i686"
)
message("++ Adding SSE and AES-NI flags for processor ${CMAKE_SYSTEM_PROCESSOR}")
add_compile_options(
-maes
-mrdrnd
-mpclmul
-msse
-msse2
-msse3
-msse4.1
)
endif()
if(ZT_TRACE)
add_definitions(-DZT_TRACE)
add_compile_options(-maes -mrdrnd -mpclmul -msse -msse2)
endif()
add_subdirectory(node)

View file

@ -404,7 +404,7 @@ public:
*/
ZT_ALWAYS_INLINE const uint8_t *rBnc(int &ii,unsigned int len) const noexcept
{
const uint8_t *const b = b + ii;
const uint8_t *const b = unsafeData + ii;
return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
}

View file

@ -1054,7 +1054,7 @@ ZT_ALWAYS_INLINE crypto_uint32 lt(crypto_uint32 a,crypto_uint32 b) /* 16-bit inp
return x;
}
oid reduce_add_sub(sc25519 *r)
void reduce_add_sub(sc25519 *r)
{
crypto_uint32 pb = 0;
crypto_uint32 b;

View file

@ -41,7 +41,6 @@ set(core_headers
SHA512.hpp
SharedPtr.hpp
Tag.hpp
Tests.h
Topology.hpp
Trace.hpp
TriviallyCopyable.hpp
@ -78,7 +77,6 @@ set(core_src
SelfAwareness.cpp
SHA512.cpp
Tag.cpp
Tests.cpp
Topology.cpp
Trace.cpp
Utils.cpp
@ -89,3 +87,7 @@ set(core_src
add_library(${PROJECT_NAME} STATIC ${core_src} ${core_headers})
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_BINARY_DIR})
add_executable(zt_core_tests Tests.h Tests.cpp)
target_compile_definitions(zt_core_tests PRIVATE ZT_ENABLE_TESTS=1 ZT_STANDALONE_TESTS=1)
target_link_libraries(zt_core_tests zt_core)

View file

@ -53,10 +53,8 @@ static ZT_ALWAYS_INLINE Credential::VerifyResult _credVerify(const RuntimeEnviro
return Credential::VERIFY_BAD_SIGNATURE;
const SharedPtr<Peer> peer(RR->topology->peer(tPtr,signedBy));
if (!peer) {
RR->sw->requestWhois(tPtr,RR->node->now(),signedBy);
if (!peer)
return Credential::VERIFY_NEED_IDENTITY;
}
try {
int l = credential.marshal(tmp,true);
@ -78,10 +76,8 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *const RR,
return Credential::VERIFY_BAD_SIGNATURE;
const SharedPtr<Peer> peer(RR->topology->peer(tPtr,credential._signedBy));
if (!peer) {
RR->sw->requestWhois(tPtr,RR->node->now(),credential._signedBy);
if (!peer)
return Credential::VERIFY_NEED_IDENTITY;
}
uint64_t buf[ZT_NETWORK_COM_MAX_QUALIFIERS * 3];
unsigned int ptr = 0;
@ -123,7 +119,6 @@ Credential::VerifyResult Credential::_verify(const RuntimeEnvironment *RR,void *
if (!peer->identity().verify(tmp,(unsigned int)l,credential._custody[c].signature,credential._custody[c].signatureLength))
return Credential::VERIFY_BAD_SIGNATURE;
} else {
RR->sw->requestWhois(tPtr,RR->node->now(),credential._custody[c].from);
return Credential::VERIFY_NEED_IDENTITY;
}
}

View file

@ -22,7 +22,6 @@
namespace ZeroTier {
Membership::Membership() :
_lastUpdatedMulticast(0),
_comRevocationThreshold(0),
_lastPushedCredentials(0),
_revocations(4),

View file

@ -167,9 +167,6 @@ private:
}
}
// Last time we pushed MULTICAST_LIKE(s)
int64_t _lastUpdatedMulticast;
// Revocation threshold for COM or 0 if none
int64_t _comRevocationThreshold;

View file

@ -28,16 +28,54 @@
#include "ScopedPtr.hpp"
#include "Locator.hpp"
#include "Protocol.hpp"
#include "Expect.hpp"
#include "VL1.hpp"
#include "VL2.hpp"
namespace ZeroTier {
namespace {
struct _NodeObjects
{
ZT_ALWAYS_INLINE _NodeObjects(RuntimeEnvironment *const RR,void *const tPtr) :
t(RR),
expect(),
vl2(RR),
vl1(RR),
sa(RR),
topology(RR,tPtr)
{
RR->t = &t;
RR->expect = &expect;
RR->vl2 = &vl2;
RR->vl1 = &vl1;
RR->sa = &sa;
RR->topology = &topology;
}
Trace t;
Expect expect;
VL2 vl2;
VL1 vl1;
SelfAwareness sa;
Topology topology;
};
struct _sortPeerPtrsByAddress
{
ZT_ALWAYS_INLINE bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b) const { return (a->address() < b->address()); }
};
} // anonymous namespace
Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64_t now) :
_RR(this),
_objects(nullptr),
RR(&_RR),
_cb(*callbacks),
_uPtr(uPtr),
_networks(),
_networksMask(63),
_networksMask(15),
_now(now),
_lastPing(0),
_lastHousekeepingRun(0),
@ -46,7 +84,7 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
_natMustDie(true),
_online(false)
{
_networks.resize(64); // _networksMask + 1, must be power of two
_networks.resize(16); // _networksMask + 1, must be power of two
uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0;
std::vector<uint8_t> data(stateObjectGet(tPtr,ZT_STATE_OBJECT_IDENTITY_SECRET,idtmp));
@ -74,30 +112,9 @@ Node::Node(void *uPtr,void *tPtr,const struct ZT_Node_Callbacks *callbacks,int64
stateObjectPut(tPtr,ZT_STATE_OBJECT_IDENTITY_PUBLIC,idtmp,RR->publicIdentityStr,(unsigned int)strlen(RR->publicIdentityStr));
}
#if 0
char *m = nullptr;
try {
m = reinterpret_cast<char *>(malloc(16 + sizeof(Trace) + sizeof(Switch) + sizeof(Topology) + sizeof(SelfAwareness)));
if (!m)
throw std::bad_alloc();
RR->rtmem = m;
while (((uintptr_t)m & 0xfU) != 0) ++m;
RR->t = new (m) Trace(RR);
m += sizeof(Trace);
RR->sw = new (m) Switch(RR);
m += sizeof(Switch);
RR->topology = new (m) Topology(RR,RR->identity,tPtr);
m += sizeof(Topology);
RR->sa = new (m) SelfAwareness(RR);
} catch ( ... ) {
if (RR->sa) RR->sa->~SelfAwareness();
if (RR->topology) RR->topology->~Topology();
if (RR->sw) RR->sw->~Switch();
if (RR->t) RR->t->~Trace();
if (m) ::free(m);
throw;
}
#endif
// This constructs all the components of the ZeroTier core within a single contiguous memory container,
// which reduces memory fragmentation and may improve cache locality.
_objects = new _NodeObjects(RR,tPtr);
postEvent(tPtr, ZT_EVENT_UP);
}
@ -112,13 +129,12 @@ Node::~Node()
networks.swap(_networks);
}
networks.clear();
_networks_m.lock();
_networks_m.unlock();
if (RR->sa) RR->sa->~SelfAwareness();
if (RR->topology) RR->topology->~Topology();
if (RR->t) RR->t->~Trace();
free(RR->rtmem);
if (_objects)
delete (_NodeObjects *)_objects;
// Let go of cached Buf objects. If other nodes happen to be running in this
// same process space new Bufs will be allocated as needed, but this is almost
@ -129,11 +145,12 @@ Node::~Node()
void Node::shutdown(void *tPtr)
{
RR->topology->saveAll(tPtr);
if (RR->topology)
RR->topology->saveAll(tPtr);
}
ZT_ResultCode Node::processWirePacket(
void *tptr,
void *tPtr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
@ -142,12 +159,16 @@ ZT_ResultCode Node::processWirePacket(
volatile int64_t *nextBackgroundTaskDeadline)
{
_now = now;
//RR->sw->onRemotePacket(tptr,localSocket,*(reinterpret_cast<const InetAddress *>(remoteAddress)),packetData,packetLength);
// TODO: add buffer life cycle methods
SharedPtr<Buf> tmp(new Buf());
packetLength &= ZT_BUF_MEM_MASK;
memcpy(tmp->unsafeData,packetData,packetLength);
RR->vl1->onRemotePacket(tPtr,localSocket,(remoteAddress) ? InetAddress::NIL : *asInetAddress(remoteAddress),tmp,packetLength);
return ZT_RESULT_OK;
}
ZT_ResultCode Node::processVirtualNetworkFrame(
void *tptr,
void *tPtr,
int64_t now,
uint64_t nwid,
uint64_t sourceMac,
@ -389,11 +410,11 @@ ZT_ResultCode Node::leave(uint64_t nwid,void **uptr,void *tptr)
return ZT_RESULT_OK;
}
ZT_ResultCode Node::multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
ZT_ResultCode Node::multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi)
{
SharedPtr<Network> nw(this->network(nwid));
if (nw) {
nw->multicastSubscribe(tptr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
nw->multicastSubscribe(tPtr,MulticastGroup(MAC(multicastGroup),(uint32_t)(multicastAdi & 0xffffffff)));
return ZT_RESULT_OK;
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
@ -407,18 +428,18 @@ ZT_ResultCode Node::multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,u
} else return ZT_RESULT_ERROR_NETWORK_NOT_FOUND;
}
ZT_ResultCode Node::addRoot(void *tptr,const ZT_Identity *identity,const sockaddr_storage *bootstrap)
ZT_ResultCode Node::addRoot(void *tPtr,const ZT_Identity *identity,const sockaddr_storage *bootstrap)
{
if (!identity)
return ZT_RESULT_ERROR_BAD_PARAMETER;
InetAddress a;
if (bootstrap)
a = bootstrap;
RR->topology->addRoot(tptr,*reinterpret_cast<const Identity *>(identity),a);
RR->topology->addRoot(tPtr,*reinterpret_cast<const Identity *>(identity),a);
return ZT_RESULT_OK;
}
ZT_ResultCode Node::removeRoot(void *tptr,const ZT_Identity *identity)
ZT_ResultCode Node::removeRoot(void *tPtr,const ZT_Identity *identity)
{
if (!identity)
return ZT_RESULT_ERROR_BAD_PARAMETER;
@ -440,8 +461,6 @@ void Node::status(ZT_NodeStatus *status) const
status->online = _online ? 1 : 0;
}
struct _sortPeerPtrsByAddress { inline bool operator()(const SharedPtr<Peer> &a,const SharedPtr<Peer> &b) const { return (a->address() < b->address()); } };
ZT_PeerList *Node::peers() const
{
std::vector< SharedPtr<Peer> > peers;
@ -463,7 +482,7 @@ ZT_PeerList *Node::peers() const
p->address = (*pi)->address().toInt();
identities[pl->peerCount] = (*pi)->identity(); // need to make a copy in case peer gets deleted
p->identity = &identities[pl->peerCount];
memcpy(p->identityHash,(*pi)->identity().hash(),sizeof(p->identityHash));
memcpy(p->identityHash,(*pi)->identity().hash().data(),ZT_IDENTITY_HASH_SIZE);
if ((*pi)->remoteVersionKnown()) {
p->versionMajor = (int)(*pi)->remoteVersionMajor();
p->versionMinor = (int)(*pi)->remoteVersionMinor();
@ -568,11 +587,14 @@ int Node::sendUserMessage(void *tptr,uint64_t dest,uint64_t typeId,const void *d
{
try {
if (RR->identity.address().toInt() != dest) {
// TODO
/*
Packet outp(Address(dest),RR->identity.address(),Packet::VERB_USER_MESSAGE);
outp.append(typeId);
outp.append(data,len);
outp.compress();
RR->sw->send(tptr,outp,true);
*/
return 1;
}
} catch ( ... ) {}
@ -586,9 +608,7 @@ void Node::setController(void *networkControllerInstance)
RR->localNetworkController->init(RR->identity,this);
}
/****************************************************************************/
/* Node methods used only within node/ */
/****************************************************************************/
// Methods used only within the core ----------------------------------------------------------------------------------
std::vector<uint8_t> Node::stateObjectGet(void *const tPtr,ZT_StateObjectType type,const uint64_t id[2])
{
@ -671,6 +691,8 @@ bool Node::localControllerHasAuthorized(const int64_t now,const uint64_t nwid,co
return false;
}
// Implementation of NetworkController::Sender ------------------------------------------------------------------------
void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &destination,const NetworkConfig &nc,bool sendLegacyFormatConfig)
{
_localControllerAuthorizations_m.lock();
@ -682,12 +704,15 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
if (!n) return;
n->setConfiguration((void *)0,nc,true);
} else {
ScopedPtr< Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY> > dconf(new Dictionary<ZT_NETWORKCONFIG_DICT_CAPACITY>());
if (nc.toDictionary(*dconf,sendLegacyFormatConfig)) {
Dictionary dconf;
if (nc.toDictionary(dconf,sendLegacyFormatConfig)) {
uint64_t configUpdateId = Utils::random();
if (!configUpdateId) ++configUpdateId;
const unsigned int totalSize = dconf->sizeBytes();
std::vector<uint8_t> ddata;
dconf.encode(ddata);
// TODO
/*
unsigned int chunkIndex = 0;
while (chunkIndex < totalSize) {
const unsigned int chunkLen = std::min(totalSize - chunkIndex,(unsigned int)(ZT_PROTO_MAX_PACKET_LENGTH - (ZT_PACKET_IDX_PAYLOAD + 256)));
@ -717,6 +742,7 @@ void Node::ncSendConfig(uint64_t nwid,uint64_t requestPacketId,const Address &de
RR->sw->send((void *)0,outp,true);
chunkIndex += chunkLen;
}
*/
}
}
}
@ -728,6 +754,8 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
if (!n) return;
n->addCredential((void *)0,RR->identity,rev);
} else {
// TODO
/*
Packet outp(destination,RR->identity.address(),Packet::VERB_NETWORK_CREDENTIALS);
outp.append((uint8_t)0x00);
outp.append((uint16_t)0);
@ -736,6 +764,7 @@ void Node::ncSendRevocation(const Address &destination,const Revocation &rev)
rev.serialize(outp);
outp.append((uint16_t)0);
RR->sw->send((void *)0,outp,true);
*/
}
}
@ -756,6 +785,8 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
default: break;
}
} else if (requestPacketId) {
// TODO
/*
Packet outp(destination,RR->identity.address(),Packet::VERB_ERROR);
outp.append((unsigned char)Packet::VERB_NETWORK_CONFIG_REQUEST);
outp.append(requestPacketId);
@ -771,14 +802,13 @@ void Node::ncSendError(uint64_t nwid,uint64_t requestPacketId,const Address &des
}
outp.append(nwid);
RR->sw->send((void *)0,outp,true);
*/
} // else we can't send an ERROR() in response to nothing, so discard
}
} // namespace ZeroTier
/****************************************************************************/
/* CAPI bindings */
/****************************************************************************/
// C API exports
extern "C" {
@ -1015,9 +1045,12 @@ enum ZT_ResultCode ZT_Node_setPhysicalPathConfiguration(ZT_Node *node,const stru
void ZT_version(int *major,int *minor,int *revision)
{
if (major) *major = ZEROTIER_ONE_VERSION_MAJOR;
if (minor) *minor = ZEROTIER_ONE_VERSION_MINOR;
if (revision) *revision = ZEROTIER_ONE_VERSION_REVISION;
if (major)
*major = ZEROTIER_ONE_VERSION_MAJOR;
if (minor)
*minor = ZEROTIER_ONE_VERSION_MINOR;
if (revision)
*revision = ZEROTIER_ONE_VERSION_REVISION;
}
} // extern "C"

View file

@ -68,7 +68,7 @@ public:
// Public API Functions ---------------------------------------------------------------------------------------------
ZT_ResultCode processWirePacket(
void *tptr,
void *tPtr,
int64_t now,
int64_t localSocket,
const struct sockaddr_storage *remoteAddress,
@ -76,7 +76,7 @@ public:
unsigned int packetLength,
volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode processVirtualNetworkFrame(
void *tptr,
void *tPtr,
int64_t now,
uint64_t nwid,
uint64_t sourceMac,
@ -89,10 +89,10 @@ public:
ZT_ResultCode processBackgroundTasks(void *tPtr, int64_t now, volatile int64_t *nextBackgroundTaskDeadline);
ZT_ResultCode join(uint64_t nwid,void *uptr,void *tptr);
ZT_ResultCode leave(uint64_t nwid,void **uptr,void *tptr);
ZT_ResultCode multicastSubscribe(void *tptr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode multicastSubscribe(void *tPtr,uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode multicastUnsubscribe(uint64_t nwid,uint64_t multicastGroup,unsigned long multicastAdi);
ZT_ResultCode addRoot(void *tptr,const ZT_Identity *identity,const sockaddr_storage *bootstrap);
ZT_ResultCode removeRoot(void *tptr,const ZT_Identity *identity);
ZT_ResultCode addRoot(void *tPtr,const ZT_Identity *identity,const sockaddr_storage *bootstrap);
ZT_ResultCode removeRoot(void *tPtr,const ZT_Identity *identity);
uint64_t address() const;
void status(ZT_NodeStatus *status) const;
ZT_PeerList *peers() const;
@ -331,6 +331,7 @@ public:
private:
RuntimeEnvironment _RR;
void *_objects;
RuntimeEnvironment *RR;
ZT_Node_Callbacks _cb;
void *_uPtr; // _uptr (lower case) is reserved in Visual Studio :P

View file

@ -594,4 +594,15 @@ extern "C" const char *ZTT_benchmarkCrypto()
return nullptr;
}
#ifdef ZT_STANDALONE_TESTS
int main(int argc,char **argv)
{
bool ok = true;
ok &= ZTT_general() == nullptr;
ZT_T_PRINTF(ZT_EOL_S);
ok &= ZTT_crypto() == nullptr;
return ok ? 0 : 1;
}
#endif
#endif // ZT_ENABLE_TESTS

View file

@ -37,8 +37,6 @@
#ifndef ZT_TESTS_HPP
#define ZT_TESTS_HPP
#define ZT_ENABLE_TESTS
#ifdef ZT_ENABLE_TESTS
#ifdef __cplusplus

View file

@ -34,9 +34,8 @@ struct _RootSortComparisonOperator
const int64_t _now;
};
Topology::Topology(const RuntimeEnvironment *renv,const Identity &myId,void *tPtr) :
Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) :
RR(renv),
_myIdentity(myId),
_numConfiguredPhysicalPaths(0),
_peers(256),
_peersByIncomingProbe(256),
@ -147,7 +146,7 @@ void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathN
void Topology::addRoot(void *tPtr,const Identity &id,const InetAddress &bootstrap)
{
if (id == _myIdentity) return; // sanity check
if (id == RR->identity) return; // sanity check
RWMutex::Lock l1(_peers_l);
std::pair< std::set<Identity>::iterator,bool > ir(_roots.insert(id));
if (ir.second) {

View file

@ -42,7 +42,7 @@ class RuntimeEnvironment;
class Topology
{
public:
Topology(const RuntimeEnvironment *renv,const Identity &myId,void *tPtr);
Topology(const RuntimeEnvironment *renv,void *tPtr);
~Topology();
/**
@ -355,7 +355,6 @@ private:
}
const RuntimeEnvironment *const RR;
const Identity _myIdentity;
RWMutex _peers_l;
RWMutex _paths_l;

View file

@ -288,92 +288,6 @@ static ZT_ALWAYS_INLINE unsigned long hashString(const void *restrict key,const
return h;
}
/**
* Decode a big-endian value from a byte stream
*
* @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
* @param p Byte stream, must be at least sizeof(I) in size
* @return Decoded integer
*/
template<typename I>
static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
I x = (I)0;
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
#else
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
#endif
}
return x;
#else
return ntoh(*reinterpret_cast<const I *>(p));
#endif
}
/**
* Save an integer in big-endian format
*
* @tparam I Integer type to store (usually inferred)
* @param p Byte stream to write (must be at least sizeof(I))
* #param i Integer to write
*/
template<typename I>
static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
#else
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
#endif
}
#else
*reinterpret_cast<I *>(p) = hton(i);
#endif
}
/**
* Copy bits from memory into an integer type without modifying their order
*
* @tparam I Type to load
* @param p Byte stream, must be at least sizeof(I) in size
* @return Loaded raw integer
*/
template<typename I>
static ZT_ALWAYS_INLINE I loadAsIsEndian(const void *const p) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
I x = (I)0;
for(unsigned int k=0;k<sizeof(I);++k)
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
return x;
#else
return *reinterpret_cast<const I *>(p);
#endif
}
/**
* Copy bits from memory into an integer type without modifying their order
*
* @tparam I Type to store
* @param p Byte array (must be at least sizeof(I))
* @param i Integer to store
*/
template<typename I>
static ZT_ALWAYS_INLINE void storeAsIsEndian(void *const p,const I i) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k)
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
#else
*reinterpret_cast<I *>(p) = i;
#endif
}
#ifdef __GNUC__
static ZT_ALWAYS_INLINE unsigned int countBits(const uint8_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
static ZT_ALWAYS_INLINE unsigned int countBits(const uint16_t v) noexcept { return (unsigned int)__builtin_popcount((unsigned int)v); }
@ -502,6 +416,92 @@ template<typename T>
static ZT_ALWAYS_INLINE T ntoh(T n) noexcept { return n; }
#endif
/**
* Decode a big-endian value from a byte stream
*
* @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
* @param p Byte stream, must be at least sizeof(I) in size
* @return Decoded integer
*/
template<typename I>
static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
I x = (I)0;
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
#else
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
#endif
}
return x;
#else
return ntoh(*reinterpret_cast<const I *>(p));
#endif
}
/**
* Save an integer in big-endian format
*
* @tparam I Integer type to store (usually inferred)
* @param p Byte stream to write (must be at least sizeof(I))
* #param i Integer to write
*/
template<typename I>
static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
#else
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
#endif
}
#else
*reinterpret_cast<I *>(p) = hton(i);
#endif
}
/**
* Copy bits from memory into an integer type without modifying their order
*
* @tparam I Type to load
* @param p Byte stream, must be at least sizeof(I) in size
* @return Loaded raw integer
*/
template<typename I>
static ZT_ALWAYS_INLINE I loadAsIsEndian(const void *const p) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
I x = (I)0;
for(unsigned int k=0;k<sizeof(I);++k)
reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
return x;
#else
return *reinterpret_cast<const I *>(p);
#endif
}
/**
* Copy bits from memory into an integer type without modifying their order
*
* @tparam I Type to store
* @param p Byte array (must be at least sizeof(I))
* @param i Integer to store
*/
template<typename I>
static ZT_ALWAYS_INLINE void storeAsIsEndian(void *const p,const I i) noexcept
{
#ifdef ZT_NO_UNALIGNED_ACCESS
for(unsigned int k=0;k<sizeof(I);++k)
reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
#else
*reinterpret_cast<I *>(p) = i;
#endif
}
} // namespace Utils
} // namespace ZeroTier