Merge branch 'dev' into hello-encryption

# Conflicts:
#	controller/DB.hpp
#	controller/DBMirrorSet.cpp
#	controller/DBMirrorSet.hpp
#	controller/EmbeddedNetworkController.cpp
#	controller/FileDB.cpp
#	controller/FileDB.hpp
#	controller/LFDB.cpp
#	controller/LFDB.hpp
#	controller/PostgreSQL.cpp
#	controller/PostgreSQL.hpp
#	node/C25519.cpp
#	node/C25519.hpp
#	node/Capability.hpp
#	node/CertificateOfMembership.cpp
#	node/CertificateOfMembership.hpp
#	node/CertificateOfOwnership.hpp
#	node/Credential.hpp
#	node/Identity.cpp
#	node/Identity.hpp
#	node/IncomingPacket.cpp
#	node/Metrics.cpp
#	node/Metrics.hpp
#	node/Multicaster.cpp
#	node/Network.cpp
#	node/Node.cpp
#	node/Packet.cpp
#	node/Packet.hpp
#	node/Peer.cpp
#	node/Revocation.hpp
#	node/Switch.cpp
#	node/Tag.hpp
#	node/World.hpp
#	osdep/Http.hpp
#	service/OneService.cpp
This commit is contained in:
Adam Ierymenko 2025-07-03 12:10:57 -04:00
commit ce708df877
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
32 changed files with 3589 additions and 2164 deletions

View file

@ -31,3 +31,6 @@ drone:
@echo "rendering .drone.yaml from .drone.jsonnet" @echo "rendering .drone.yaml from .drone.jsonnet"
drone jsonnet --format --stream drone jsonnet --format --stream
drone sign zerotier/ZeroTierOne --save drone sign zerotier/ZeroTierOne --save
clang-format:
find node osdep service tcp-proxy controller -iname '*.cpp' -o -iname '*.hpp' | xargs clang-format -i

1952
controller/CV1.cpp Normal file

File diff suppressed because it is too large Load diff

141
controller/CV1.hpp Normal file
View file

@ -0,0 +1,141 @@
/*
* Copyright (c)2019 ZeroTier, Inc.
*
* Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory.
*
* Change Date: 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.
*/
/****/
#include "DB.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#ifndef ZT_CONTROLLER_CV1_HPP
#define ZT_CONTROLLER_CV1_HPP
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
#include "../node/Metrics.hpp"
#include "ConnectionPool.hpp"
#include "PostgreSQL.hpp"
#include <memory>
#include <pqxx/pqxx>
#include <redis++/redis++.h>
namespace smeeclient {
struct SmeeClient;
}
namespace ZeroTier {
struct RedisConfig;
/**
* A controller database driver that talks to PostgreSQL
*
* This is for use with ZeroTier Central. Others are free to build and use it
* but be aware that we might change it at any time.
*/
class CV1 : public DB {
public:
CV1(const Identity& myId, const char* path, int listenPort, RedisConfig* rc);
virtual ~CV1();
virtual bool waitForReady();
virtual bool isReady();
virtual bool save(nlohmann::json& record, bool notifyListeners);
virtual void eraseNetwork(const uint64_t networkId);
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch);
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL);
virtual bool ready()
{
return _ready == 2;
}
protected:
struct _PairHasher {
inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const
{
return (std::size_t)(p.first ^ p.second);
}
};
virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners)
{
DB::_memberChanged(old, memberConfig, notifyListeners);
}
virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners)
{
DB::_networkChanged(old, networkConfig, notifyListeners);
}
private:
void initializeNetworks();
void initializeMembers();
void heartbeat();
void membersDbWatcher();
void _membersWatcher_Postgres();
void networksDbWatcher();
void _networksWatcher_Postgres();
void _membersWatcher_Redis();
void _networksWatcher_Redis();
void commitThread();
void onlineNotificationThread();
void onlineNotification_Postgres();
void onlineNotification_Redis();
uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher>& lastOnline);
void configureSmee();
void notifyNewMember(const std::string& networkID, const std::string& memberID);
enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 };
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool;
const Identity _myId;
const Address _myAddress;
std::string _myAddressStr;
std::string _connString;
BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue;
std::thread _heartbeatThread;
std::thread _membersDbWatcher;
std::thread _networksDbWatcher;
std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
std::thread _onlineNotificationThread;
std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher> _lastOnline;
mutable std::mutex _lastOnline_l;
mutable std::mutex _readyLock;
std::atomic<int> _ready, _connected, _run;
mutable volatile bool _waitNoticePrinted;
int _listenPort;
uint8_t _ssoPsk[48];
RedisConfig* _rc;
std::shared_ptr<sw::redis::Redis> _redis;
std::shared_ptr<sw::redis::RedisCluster> _cluster;
bool _redisMemberStatus;
smeeclient::SmeeClient* _smee;
};
} // namespace ZeroTier
#endif // ZT_CONTROLLER_CV1_HPP
#endif // ZT_CONTROLLER_USE_LIBPQ

1104
controller/CV2.cpp Normal file

File diff suppressed because it is too large Load diff

112
controller/CV2.hpp Normal file
View file

@ -0,0 +1,112 @@
/*
* Copyright (c)2025 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.
*/
/****/
#include "DB.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#ifndef ZT_CONTROLLER_CV2_HPP
#define ZT_CONTROLLER_CV2_HPP
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
#include "../node/Metrics.hpp"
#include "ConnectionPool.hpp"
#include "PostgreSQL.hpp"
#include <memory>
#include <pqxx/pqxx>
#include <redis++/redis++.h>
namespace ZeroTier {
class CV2 : public DB {
public:
CV2(const Identity& myId, const char* path, int listenPort);
virtual ~CV2();
virtual bool waitForReady();
virtual bool isReady();
virtual bool save(nlohmann::json& record, bool notifyListeners);
virtual void eraseNetwork(const uint64_t networkId);
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch);
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL);
virtual bool ready()
{
return _ready == 2;
}
protected:
struct _PairHasher {
inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const
{
return (std::size_t)(p.first ^ p.second);
}
};
virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners)
{
DB::_memberChanged(old, memberConfig, notifyListeners);
}
virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners)
{
DB::_networkChanged(old, networkConfig, notifyListeners);
}
private:
void initializeNetworks();
void initializeMembers();
void heartbeat();
void membersDbWatcher();
void networksDbWatcher();
void commitThread();
void onlineNotificationThread();
// void notifyNewMember(const std::string &networkID, const std::string &memberID);
enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 };
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool;
const Identity _myId;
const Address _myAddress;
std::string _myAddressStr;
std::string _connString;
BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue;
std::thread _heartbeatThread;
std::thread _membersDbWatcher;
std::thread _networksDbWatcher;
std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
std::thread _onlineNotificationThread;
std::unordered_map<std::pair<uint64_t, uint64_t>, NodeOnlineRecord, _PairHasher> _lastOnline;
mutable std::mutex _lastOnline_l;
mutable std::mutex _readyLock;
std::atomic<int> _ready, _connected, _run;
mutable volatile bool _waitNoticePrinted;
int _listenPort;
uint8_t _ssoPsk[48];
};
} // namespace ZeroTier
#endif // ZT_CONTROLLER_CV2_HPP
#endif // ZT_CONTROLLER_USE_LIBPQ

64
controller/CtlUtil.cpp Normal file
View file

@ -0,0 +1,64 @@
#include "CtlUtil.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ
#include <iomanip>
#include <sstream>
namespace ZeroTier {
const char* _timestr()
{
time_t t = time(0);
char* ts = ctime(&t);
char* p = ts;
if (! p)
return "";
while (*p) {
if (*p == '\n') {
*p = (char)0;
break;
}
++p;
}
return ts;
}
std::vector<std::string> split(std::string str, char delim)
{
std::istringstream iss(str);
std::vector<std::string> tokens;
std::string item;
while (std::getline(iss, item, delim)) {
tokens.push_back(item);
}
return tokens;
}
std::string url_encode(const std::string& value)
{
std::ostringstream escaped;
escaped.fill('0');
escaped << std::hex;
for (std::string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
std::string::value_type c = (*i);
// Keep alphanumeric and other accepted characters intact
if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
escaped << c;
continue;
}
// Any other characters are percent-encoded
escaped << std::uppercase;
escaped << '%' << std::setw(2) << int((unsigned char)c);
escaped << std::nouppercase;
}
return escaped.str();
}
} // namespace ZeroTier
#endif

16
controller/CtlUtil.hpp Normal file
View file

@ -0,0 +1,16 @@
#ifndef ZT_CTLUTIL_HPP
#define ZT_CTLUTIL_HPP
#include <string>
#include <vector>
namespace ZeroTier {
const char* _timestr();
std::vector<std::string> split(std::string str, char delim);
std::string url_encode(const std::string& value);
} // namespace ZeroTier
#endif // namespace ZeroTier

View file

@ -61,6 +61,10 @@ struct AuthInfo {
* Base class with common infrastructure for all controller DB implementations * Base class with common infrastructure for all controller DB implementations
*/ */
class DB { class DB {
#ifdef ZT_CONTROLLER_USE_LIBPQ
friend class MemberNotificationReceiver;
friend class NetworkNotificationReceiver;
#endif
public: public:
class ChangeListener { class ChangeListener {
public: public:
@ -132,6 +136,7 @@ class DB {
virtual void eraseNetwork(const uint64_t networkId) = 0; virtual void eraseNetwork(const uint64_t networkId) = 0;
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId) = 0; virtual void eraseMember(const uint64_t networkId, const uint64_t memberId) = 0;
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) = 0; virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) = 0;
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch) = 0;
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL) virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL)
{ {

View file

@ -205,14 +205,19 @@ void DBMirrorSet::eraseMember(const uint64_t networkId, const uint64_t memberId)
} }
} }
void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch)
{ {
std::shared_lock<std::shared_mutex> l(_dbs_l); std::shared_lock<std::shared_mutex> l(_dbs_l);
for (auto d = _dbs.begin(); d != _dbs.end(); ++d) { for (auto d = _dbs.begin(); d != _dbs.end(); ++d) {
(*d)->nodeIsOnline(networkId, memberId, physicalAddress); (*d)->nodeIsOnline(networkId, memberId, physicalAddress, osArch);
} }
} }
void DBMirrorSet::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
{
this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown");
}
void DBMirrorSet::onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network) void DBMirrorSet::onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network)
{ {
nlohmann::json record(network); nlohmann::json record(network);

View file

@ -43,7 +43,8 @@ class DBMirrorSet : public DB::ChangeListener {
bool save(nlohmann::json& record, bool notifyListeners); bool save(nlohmann::json& record, bool notifyListeners);
void eraseNetwork(const uint64_t networkId); void eraseNetwork(const uint64_t networkId);
void eraseMember(const uint64_t networkId, const uint64_t memberId); void eraseMember(const uint64_t networkId, const uint64_t memberId);
void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch);
// These are called by various DB instances when changes occur. // These are called by various DB instances when changes occur.
virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network); virtual void onNetworkUpdate(const void* db, uint64_t networkId, const nlohmann::json& network);

View file

@ -38,7 +38,8 @@
#include <thread> #include <thread>
#include <utility> #include <utility>
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
#include "PostgreSQL.hpp" #include "CV1.hpp"
#include "CV2.hpp"
#endif #endif
#include "../node/CertificateOfMembership.hpp" #include "../node/CertificateOfMembership.hpp"
@ -594,9 +595,15 @@ void EmbeddedNetworkController::init(const Identity& signingId, Sender* sender)
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
if ((_path.length() > 9) && (_path.substr(0, 9) == "postgres:")) { if ((_path.length() > 9) && (_path.substr(0, 9) == "postgres:")) {
_db.addDB(std::shared_ptr<DB>(new PostgreSQL(_signingId, _path.substr(9).c_str(), _listenPort, _rc))); fprintf(stderr, "CV1\n");
_db.addDB(std::shared_ptr<DB>(new CV1(_signingId, _path.substr(9).c_str(), _listenPort, _rc)));
}
else if ((_path.length() > 4) && (_path.substr(0, 4) == "cv2:")) {
fprintf(stderr, "CV2\n");
_db.addDB(std::shared_ptr<DB>(new CV2(_signingId, _path.substr(4).c_str(), _listenPort)));
} }
else { else {
fprintf(stderr, "FileDB\n");
#endif #endif
_db.addDB(std::shared_ptr<DB>(new FileDB(_path.c_str()))); _db.addDB(std::shared_ptr<DB>(new FileDB(_path.c_str())));
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
@ -1496,7 +1503,11 @@ void EmbeddedNetworkController::_request(uint64_t nwid, const InetAddress& fromA
c2++; c2++;
b2.start(); b2.start();
#endif #endif
_db.nodeIsOnline(nwid, identity.address().toInt(), fromAddr); char osArch[256];
metaData.get(ZT_NETWORKCONFIG_REQUEST_METADATA_KEY_OS_ARCH, osArch, sizeof(osArch));
// fprintf(stderr, "Network Config Request: nwid=%.16llx, nodeid=%.10llx, osArch=%s\n",
// nwid, identity.address().toInt(), osArch);
_db.nodeIsOnline(nwid, identity.address().toInt(), fromAddr, osArch);
#ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK #ifdef CENTRAL_CONTROLLER_REQUEST_BENCHMARK
b2.stop(); b2.stop();

View file

@ -160,7 +160,7 @@ void FileDB::eraseMember(const uint64_t networkId, const uint64_t memberId)
this->_online[networkId].erase(memberId); this->_online[networkId].erase(memberId);
} }
void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch)
{ {
char mid[32], atmp[64]; char mid[32], atmp[64];
OSUtils::ztsnprintf(mid, sizeof(mid), "%.10llx", (unsigned long long)memberId); OSUtils::ztsnprintf(mid, sizeof(mid), "%.10llx", (unsigned long long)memberId);
@ -169,4 +169,9 @@ void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, con
this->_online[networkId][memberId][OSUtils::now()] = physicalAddress; this->_online[networkId][memberId][OSUtils::now()] = physicalAddress;
} }
void FileDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
{
this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown");
}
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -29,6 +29,7 @@ class FileDB : public DB {
virtual void eraseNetwork(const uint64_t networkId); virtual void eraseNetwork(const uint64_t networkId);
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch);
protected: protected:
std::string _path; std::string _path;

View file

@ -420,7 +420,7 @@ void LFDB::eraseMember(const uint64_t networkId, const uint64_t memberId)
// TODO // TODO
} }
void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress) void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch)
{ {
std::lock_guard<std::mutex> l(_state_l); std::lock_guard<std::mutex> l(_state_l);
auto nw = _state.find(networkId); auto nw = _state.find(networkId);
@ -435,4 +435,9 @@ void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const
} }
} }
void LFDB::nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress)
{
this->nodeIsOnline(networkId, memberId, physicalAddress, "unknown/unknown");
}
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -46,6 +46,7 @@ class LFDB : public DB {
virtual void eraseNetwork(const uint64_t networkId); virtual void eraseNetwork(const uint64_t networkId);
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId); virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress); virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress, const char* osArch);
protected: protected:
const Identity _myId; const Identity _myId;

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c)2019 ZeroTier, Inc. * Copyright (c)2025 ZeroTier, Inc.
* *
* Use of this software is governed by the Business Source License included * Use of this software is governed by the Business Source License included
* in the LICENSE.TXT file in the project's root directory. * in the LICENSE.TXT file in the project's root directory.
@ -11,34 +11,23 @@
*/ */
/****/ /****/
#include "DB.hpp"
#ifdef ZT_CONTROLLER_USE_LIBPQ #ifdef ZT_CONTROLLER_USE_LIBPQ
#ifndef ZT_CONTROLLER_LIBPQ_HPP #ifndef ZT_CONTROLLER_POSTGRESQL_HPP
#define ZT_CONTROLLER_LIBPQ_HPP #define ZT_CONTROLLER_POSTGRESQL_HPP
#define ZT_CENTRAL_CONTROLLER_COMMIT_THREADS 4
#include "../node/Metrics.hpp"
#include "ConnectionPool.hpp" #include "ConnectionPool.hpp"
#include "DB.hpp"
#include <memory> #include <memory>
#include <pqxx/pqxx> #include <pqxx/pqxx>
#include <redis++/redis++.h>
namespace ZeroTier {
extern "C" { extern "C" {
typedef struct pg_conn PGconn; typedef struct pg_conn PGconn;
} }
namespace smeeclient {
struct SmeeClient;
}
namespace ZeroTier {
struct RedisConfig;
class PostgresConnection : public Connection { class PostgresConnection : public Connection {
public: public:
virtual ~PostgresConnection() virtual ~PostgresConnection()
@ -67,11 +56,9 @@ class PostgresConnFactory : public ConnectionFactory {
std::string m_connString; std::string m_connString;
}; };
class PostgreSQL;
class MemberNotificationReceiver : public pqxx::notification_receiver { class MemberNotificationReceiver : public pqxx::notification_receiver {
public: public:
MemberNotificationReceiver(PostgreSQL* p, pqxx::connection& c, const std::string& channel); MemberNotificationReceiver(DB* p, pqxx::connection& c, const std::string& channel);
virtual ~MemberNotificationReceiver() virtual ~MemberNotificationReceiver()
{ {
fprintf(stderr, "MemberNotificationReceiver destroyed\n"); fprintf(stderr, "MemberNotificationReceiver destroyed\n");
@ -80,12 +67,12 @@ class MemberNotificationReceiver : public pqxx::notification_receiver {
virtual void operator()(const std::string& payload, int backendPid); virtual void operator()(const std::string& payload, int backendPid);
private: private:
PostgreSQL* _psql; DB* _psql;
}; };
class NetworkNotificationReceiver : public pqxx::notification_receiver { class NetworkNotificationReceiver : public pqxx::notification_receiver {
public: public:
NetworkNotificationReceiver(PostgreSQL* p, pqxx::connection& c, const std::string& channel); NetworkNotificationReceiver(DB* p, pqxx::connection& c, const std::string& channel);
virtual ~NetworkNotificationReceiver() virtual ~NetworkNotificationReceiver()
{ {
fprintf(stderr, "NetworkNotificationReceiver destroyed\n"); fprintf(stderr, "NetworkNotificationReceiver destroyed\n");
@ -94,106 +81,17 @@ class NetworkNotificationReceiver : public pqxx::notification_receiver {
virtual void operator()(const std::string& payload, int packend_pid); virtual void operator()(const std::string& payload, int packend_pid);
private: private:
PostgreSQL* _psql; DB* _psql;
}; };
/** struct NodeOnlineRecord {
* A controller database driver that talks to PostgreSQL uint64_t lastSeen;
* InetAddress physicalAddress;
* This is for use with ZeroTier Central. Others are free to build and use it std::string osArch;
* but be aware that we might change it at any time.
*/
class PostgreSQL : public DB {
friend class MemberNotificationReceiver;
friend class NetworkNotificationReceiver;
public:
PostgreSQL(const Identity& myId, const char* path, int listenPort, RedisConfig* rc);
virtual ~PostgreSQL();
virtual bool waitForReady();
virtual bool isReady();
virtual bool save(nlohmann::json& record, bool notifyListeners);
virtual void eraseNetwork(const uint64_t networkId);
virtual void eraseMember(const uint64_t networkId, const uint64_t memberId);
virtual void nodeIsOnline(const uint64_t networkId, const uint64_t memberId, const InetAddress& physicalAddress);
virtual AuthInfo getSSOAuthInfo(const nlohmann::json& member, const std::string& redirectURL);
protected:
struct _PairHasher {
inline std::size_t operator()(const std::pair<uint64_t, uint64_t>& p) const
{
return (std::size_t)(p.first ^ p.second);
}
};
virtual void _memberChanged(nlohmann::json& old, nlohmann::json& memberConfig, bool notifyListeners)
{
DB::_memberChanged(old, memberConfig, notifyListeners);
}
virtual void _networkChanged(nlohmann::json& old, nlohmann::json& networkConfig, bool notifyListeners)
{
DB::_networkChanged(old, networkConfig, notifyListeners);
}
private:
void initializeNetworks();
void initializeMembers();
void heartbeat();
void membersDbWatcher();
void _membersWatcher_Postgres();
void networksDbWatcher();
void _networksWatcher_Postgres();
void _membersWatcher_Redis();
void _networksWatcher_Redis();
void commitThread();
void onlineNotificationThread();
void onlineNotification_Postgres();
void onlineNotification_Redis();
uint64_t _doRedisUpdate(sw::redis::Transaction& tx, std::string& controllerId, std::unordered_map<std::pair<uint64_t, uint64_t>, std::pair<int64_t, InetAddress>, _PairHasher>& lastOnline);
void configureSmee();
void notifyNewMember(const std::string& networkID, const std::string& memberID);
enum OverrideMode { ALLOW_PGBOUNCER_OVERRIDE = 0, NO_OVERRIDE = 1 };
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool;
const Identity _myId;
const Address _myAddress;
std::string _myAddressStr;
std::string _connString;
BlockingQueue<std::pair<nlohmann::json, bool> > _commitQueue;
std::thread _heartbeatThread;
std::thread _membersDbWatcher;
std::thread _networksDbWatcher;
std::thread _commitThread[ZT_CENTRAL_CONTROLLER_COMMIT_THREADS];
std::thread _onlineNotificationThread;
std::unordered_map<std::pair<uint64_t, uint64_t>, std::pair<int64_t, InetAddress>, _PairHasher> _lastOnline;
mutable std::mutex _lastOnline_l;
mutable std::mutex _readyLock;
std::atomic<int> _ready, _connected, _run;
mutable volatile bool _waitNoticePrinted;
int _listenPort;
uint8_t _ssoPsk[48];
RedisConfig* _rc;
std::shared_ptr<sw::redis::Redis> _redis;
std::shared_ptr<sw::redis::RedisCluster> _cluster;
bool _redisMemberStatus;
smeeclient::SmeeClient* _smee;
}; };
} // namespace ZeroTier } // namespace ZeroTier
#endif // ZT_CONTROLLER_LIBPQ_HPP #endif // ZT_CONTROLLER_POSTGRESQL_HPP
#endif // ZT_CONTROLLER_USE_LIBPQ #endif // ZT_CONTROLLER_USE_LIBPQ

View file

@ -1,11 +1,16 @@
# Dockerfile for ZeroTier Central Controllers # Dockerfile for ZeroTier Central Controllers
FROM registry.zerotier.com/zerotier/ctlbuild:latest as builder FROM registry.zerotier.com/zerotier/ctlbuild:2025-05-13-01 AS builder
MAINTAINER Adam Ierymekno <adam.ierymenko@zerotier.com>, Grant Limberg <grant.limberg@zerotier.com>
ADD . /ZeroTierOne ADD . /ZeroTierOne
RUN export PATH=$PATH:~/.cargo/bin && cd ZeroTierOne && make clean && make central-controller -j8 RUN export PATH=$PATH:~/.cargo/bin && cd ZeroTierOne && make clean && make central-controller -j8
FROM registry.zerotier.com/zerotier/ctlrun:latest FROM golang:bookworm AS go_base
RUN go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest
FROM registry.zerotier.com/zerotier/ctlrun:2025-05-13-01
COPY --from=builder /ZeroTierOne/zerotier-one /usr/local/bin/zerotier-one COPY --from=builder /ZeroTierOne/zerotier-one /usr/local/bin/zerotier-one
COPY --from=go_base /go/bin/migrate /usr/local/bin/migrate
COPY ext/central-controller-docker/migrations /migrations
RUN chmod a+x /usr/local/bin/zerotier-one RUN chmod a+x /usr/local/bin/zerotier-one
RUN echo "/usr/local/lib64" > /etc/ld.so.conf.d/usr-local-lib64.conf && ldconfig RUN echo "/usr/local/lib64" > /etc/ld.so.conf.d/usr-local-lib64.conf && ldconfig

View file

@ -1,8 +1,5 @@
# Dockerfile for building ZeroTier Central Controllers # Dockerfile for building ZeroTier Central Controllers
FROM ubuntu:jammy as builder FROM debian:bookworm
MAINTAINER Adam Ierymekno <adam.ierymenko@zerotier.com>, Grant Limberg <grant.limberg@zerotier.com>
ARG git_branch=master
RUN apt update && apt upgrade -y RUN apt update && apt upgrade -y
RUN apt -y install \ RUN apt -y install \

View file

@ -1,15 +1,17 @@
FROM ubuntu:jammy FROM debian:bookworm
RUN apt update && apt upgrade -y RUN apt update && apt upgrade -y
RUN apt -y install \ RUN apt -y install \
netcat \ netcat-traditional \
postgresql-client \ postgresql-client \
postgresql-client-common \ postgresql-client-common \
libjemalloc2 \ libjemalloc2 \
libpq5 \ libpq5 \
curl \ curl \
binutils \ binutils \
linux-tools-gke \
perf-tools-unstable \ perf-tools-unstable \
google-perftools google-perftools \
gnupg

View file

@ -1,9 +1,5 @@
#!/bin/bash #!/bin/bash
if [ -z "$ZT_IDENTITY_PATH" ]; then
echo '*** FAILED: ZT_IDENTITY_PATH environment variable is not defined'
exit 1
fi
if [ -z "$ZT_DB_HOST" ]; then if [ -z "$ZT_DB_HOST" ]; then
echo '*** FAILED: ZT_DB_HOST environment variable not defined' echo '*** FAILED: ZT_DB_HOST environment variable not defined'
exit 1 exit 1
@ -24,6 +20,9 @@ if [ -z "$ZT_DB_PASSWORD" ]; then
echo '*** FAILED: ZT_DB_PASSWORD environment variable not defined' echo '*** FAILED: ZT_DB_PASSWORD environment variable not defined'
exit 1 exit 1
fi fi
if [ -z "$ZT_DB_TYPE" ]; then
ZT_DB_TYPE="postgres"
fi
REDIS="" REDIS=""
if [ "$ZT_USE_REDIS" == "true" ]; then if [ "$ZT_USE_REDIS" == "true" ]; then
@ -56,10 +55,14 @@ fi
mkdir -p /var/lib/zerotier-one mkdir -p /var/lib/zerotier-one
pushd /var/lib/zerotier-one pushd /var/lib/zerotier-one
ln -s $ZT_IDENTITY_PATH/identity.public identity.public if [ -d "$ZT_IDENTITY_PATH" ]; then
ln -s $ZT_IDENTITY_PATH/identity.secret identity.secret echo '*** Using existing ZT identity from path $ZT_IDENTITY_PATH'
if [ -f "$ZT_IDENTITY_PATH/authtoken.secret" ]; then
ln -s $ZT_IDENTITY_PATH/authtoken.secret authtoken.secret ln -s $ZT_IDENTITY_PATH/identity.public identity.public
ln -s $ZT_IDENTITY_PATH/identity.secret identity.secret
if [ -f "$ZT_IDENTITY_PATH/authtoken.secret" ]; then
ln -s $ZT_IDENTITY_PATH/authtoken.secret authtoken.secret
fi
fi fi
popd popd
@ -70,7 +73,7 @@ APP_NAME="controller-$(cat /var/lib/zerotier-one/identity.public | cut -d ':' -f
echo "{ echo "{
\"settings\": { \"settings\": {
\"controllerDbPath\": \"postgres:host=${ZT_DB_HOST} port=${ZT_DB_PORT} dbname=${ZT_DB_NAME} user=${ZT_DB_USER} password=${ZT_DB_PASSWORD} application_name=${APP_NAME} sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}\", \"controllerDbPath\": \"${ZT_DB_TYPE}:host=${ZT_DB_HOST} port=${ZT_DB_PORT} dbname=${ZT_DB_NAME} user=${ZT_DB_USER} password=${ZT_DB_PASSWORD} application_name=${APP_NAME} sslmode=prefer sslcert=${DB_CLIENT_CERT} sslkey=${DB_CLIENT_KEY} sslrootcert=${DB_SERVER_CA}\",
\"portMappingEnabled\": true, \"portMappingEnabled\": true,
\"softwareUpdate\": \"disable\", \"softwareUpdate\": \"disable\",
\"interfacePrefixBlacklist\": [ \"interfacePrefixBlacklist\": [
@ -100,6 +103,15 @@ else
done done
fi fi
if [ "$ZT_DB_TYPE" == "cv2" ]; then
echo "Migrating database (if needed)..."
if [ -n "$DB_SERVER_CA" ]; then
/usr/local/bin/migrate -source file:///migrations -database "postgres://$ZT_DB_USER:$ZT_DB_PASSWORD@$ZT_DB_HOST:$ZT_DB_PORT/$ZT_DB_NAME?x-migrations-table=controller_migrations&sslmode=verify-full&sslrootcert=$DB_SERVER_CA&sslcert=$DB_CLIENT_CERT&sslkey=$DB_CLIENT_KEY" up
else
/usr/local/bin/migrate -source file:///migrations -database "postgres://$ZT_DB_USER:$ZT_DB_PASSWORD@$ZT_DB_HOST:$ZT_DB_PORT/$ZT_DB_NAME?x-migrations-table=controller_migrations&sslmode=disable" up
fi
fi
if [ -n "$ZT_TEMPORAL_HOST" ] && [ -n "$ZT_TEMPORAL_PORT" ]; then if [ -n "$ZT_TEMPORAL_HOST" ] && [ -n "$ZT_TEMPORAL_PORT" ]; then
echo "waiting for temporal..." echo "waiting for temporal..."
while ! nc -z ${ZT_TEMPORAL_HOST} ${ZT_TEMPORAL_PORT}; do while ! nc -z ${ZT_TEMPORAL_HOST} ${ZT_TEMPORAL_PORT}; do

View file

@ -0,0 +1,3 @@
DROP TABLE IF EXISTS network_memberships_ctl;
DROP TABLE IF EXISTS networks_ctl;
DROP TABLE IF EXISTS controllers_ctl;

View file

@ -0,0 +1,47 @@
-- inits controller db schema
CREATE TABLE IF NOT EXISTS controllers_ctl (
id text NOT NULL PRIMARY KEY,
hostname text,
last_heartbeat timestamp with time zone,
public_identity text NOT NULL,
version text
);
CREATE TABLE IF NOT EXISTS networks_ctl (
id character varying(22) NOT NULL PRIMARY KEY,
name text NOT NULL,
configuration jsonb DEFAULT '{}'::jsonb NOT NULL,
controller_id text REFERENCES controllers_ctl(id),
revision integer DEFAULT 0 NOT NULL,
last_modified timestamp with time zone DEFAULT now(),
creation_time timestamp with time zone DEFAULT now()
);
CREATE TABLE IF NOT EXISTS network_memberships_ctl (
device_id character varying(22) NOT NULL,
network_id character varying(22) NOT NULL REFERENCES networks_ctl(id),
authorized boolean,
active_bridge boolean,
ip_assignments text[],
no_auto_assign_ips boolean,
sso_exempt boolean,
authentication_expiry_time timestamp with time zone,
capabilities jsonb,
creation_time timestamp with time zone DEFAULT now(),
last_modified timestamp with time zone DEFAULT now(),
identity text DEFAULT ''::text,
last_authorized_credential text,
last_authorized_time timestamp with time zone,
last_deauthorized_time timestamp with time zone,
last_seen jsonb DEFAULT '{}'::jsonb NOT NULL, -- in the context of the network
remote_trace_level integer DEFAULT 0 NOT NULL,
remote_trace_target text DEFAULT ''::text NOT NULL,
revision integer DEFAULT 0 NOT NULL,
tags jsonb,
version_major integer DEFAULT 0 NOT NULL,
version_minor integer DEFAULT 0 NOT NULL,
version_revision integer DEFAULT 0 NOT NULL,
version_protocol integer DEFAULT 0 NOT NULL,
PRIMARY KEY (device_id, network_id)
);

View file

@ -0,0 +1,3 @@
ALTER TABLE network_memberships_ctl
DROP COLUMN os,
DROP COLUMN arch;

View file

@ -0,0 +1,3 @@
ALTER TABLE network_memberships_ctl
ADD COLUMN os TEXT NOT NULL DEFAULT 'unknown',
ADD COLUMN arch TEXT NOT NULL DEFAULT 'unknown';

View file

@ -431,6 +431,10 @@ central-controller-docker: _buildx FORCE
docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push
@echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} @echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP}
centralv2-controller-docker: _buildx FORCE
docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t us-central1-docker.pkg.dev/zerotier-421eb9/docker-images/ztcentral-controller:$(shell git rev-parse --short HEAD) -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push
@echo Image: us-central1-docker.pkg.dev/zerotier-421eb9/docker-images/ztcentral-controller:$(shell git rev-parse --short HEAD)
debug: FORCE debug: FORCE
make ZT_DEBUG=1 one make ZT_DEBUG=1 one
make ZT_DEBUG=1 selftest make ZT_DEBUG=1 selftest

View file

@ -57,9 +57,9 @@ ONE_OBJS+=ext/libnatpmp/natpmp.o ext/libnatpmp/getgateway.o ext/miniupnpc/connec
ifeq ($(ZT_CONTROLLER),1) ifeq ($(ZT_CONTROLLER),1)
MACOS_VERSION_MIN=10.15 MACOS_VERSION_MIN=10.15
override CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++ override CXXFLAGS=$(CFLAGS) -std=c++17 -stdlib=libc++
LIBS+=-L/usr/local/opt/libpqxx/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/openssl/lib/ -lpqxx -lpq -lssl -lcrypto -lgssapi_krb5 ext/redis-plus-plus-1.1.1/install/macos/lib/libredis++.a ext/hiredis-0.14.1/lib/macos/libhiredis.a LIBS+=-L/opt/homebrew/lib -L/usr/local/opt/libpqxx/lib -L/usr/local/opt/libpq/lib -L/usr/local/opt/openssl/lib/ -lpqxx -lpq -lssl -lcrypto -lgssapi_krb5 ext/redis-plus-plus-1.1.1/install/macos/lib/libredis++.a ext/hiredis-0.14.1/lib/macos/libhiredis.a rustybits/target/libsmeeclient.a
DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER_USE_REDIS -DZT_CONTROLLER DEFS+=-DZT_CONTROLLER_USE_LIBPQ -DZT_CONTROLLER_USE_REDIS -DZT_CONTROLLER
INCLUDES+=-I/usr/local/opt/libpq/include -I/usr/local/opt/libpqxx/include -Iext/hiredis-0.14.1/include/ -Iext/redis-plus-plus-1.1.1/install/macos/include/sw/ INCLUDES+=-I/opt/homebrew/include -I/opt/homebrew/opt/libpq/include -I/usr/local/opt/libpq/include -I/usr/local/opt/libpqxx/include -Iext/hiredis-0.14.1/include/ -Iext/redis-plus-plus-1.1.1/install/macos/include/sw/ -Irustybits/target/
else else
MACOS_VERSION_MIN=10.13 MACOS_VERSION_MIN=10.13
endif endif
@ -115,7 +115,11 @@ mac-agent: FORCE
osdep/MacDNSHelper.o: osdep/MacDNSHelper.mm osdep/MacDNSHelper.o: osdep/MacDNSHelper.mm
$(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o $(CXX) $(CXXFLAGS) -c osdep/MacDNSHelper.mm -o osdep/MacDNSHelper.o
ifeq ($(ZT_CONTROLLER),1)
one: zeroidc smeeclient $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent
else
one: zeroidc $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent one: zeroidc $(CORE_OBJS) $(ONE_OBJS) one.o mac-agent
endif
$(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS) rustybits/target/libzeroidc.a $(CXX) $(CXXFLAGS) -o zerotier-one $(CORE_OBJS) $(ONE_OBJS) one.o $(LIBS) rustybits/target/libzeroidc.a
# $(STRIP) zerotier-one # $(STRIP) zerotier-one
ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-idtool
@ -126,6 +130,15 @@ zerotier-one: one
zeroidc: rustybits/target/libzeroidc.a zeroidc: rustybits/target/libzeroidc.a
ifeq ($(ZT_CONTROLLER),1)
smeeclient: rustybits/target/libsmeeclient.a
rustybits/target/libsmeeclient.a: FORCE
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p smeeclient --target=x86_64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p smeeclient --target=aarch64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && lipo -create target/x86_64-apple-darwin/$(RUST_VARIANT)/libsmeeclient.a target/aarch64-apple-darwin/$(RUST_VARIANT)/libsmeeclient.a -output target/libsmeeclient.a
endif
rustybits/target/libzeroidc.a: FORCE rustybits/target/libzeroidc.a: FORCE
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=x86_64-apple-darwin $(EXTRA_CARGO_FLAGS) cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=x86_64-apple-darwin $(EXTRA_CARGO_FLAGS)
cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=aarch64-apple-darwin $(EXTRA_CARGO_FLAGS) cd rustybits && MACOSX_DEPLOYMENT_TARGET=$(MACOS_VERSION_MIN) cargo build -p zeroidc --target=aarch64-apple-darwin $(EXTRA_CARGO_FLAGS)
@ -195,6 +208,10 @@ central-controller-docker: _buildx FORCE
docker buildx build --platform linux/arm64,linux/amd64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=$(shell git name-rev --name-only HEAD) . --push docker buildx build --platform linux/arm64,linux/amd64 --no-cache -t registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=$(shell git name-rev --name-only HEAD) . --push
@echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP} @echo Image: registry.zerotier.com/zerotier-central/ztcentral-controller:${TIMESTAMP}
centralv2-controller-docker: _buildx FORCE
docker buildx build --platform linux/amd64,linux/arm64 --no-cache -t us-central1-docker.pkg.dev/zerotier-d648c7/central-v2/ztcentral-controller:${TIMESTAMP} -f ext/central-controller-docker/Dockerfile --build-arg git_branch=`git name-rev --name-only HEAD` . --push
@echo Image: us-central1-docker.pkg.dev/zerotier-d648c7/central-v2/ztcentral-controller:${TIMESTAMP}
docker-release: _buildx docker-release: _buildx
docker buildx build --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/mips64le,linux/ppc64le,linux/s390x -t zerotier/zerotier:${RELEASE_DOCKER_TAG} -t zerotier/zerotier:latest --build-arg VERSION=${RELEASE_VERSION} -f Dockerfile.release . --push docker buildx build --platform linux/386,linux/amd64,linux/arm/v7,linux/arm64,linux/mips64le,linux/ppc64le,linux/s390x -t zerotier/zerotier:${RELEASE_DOCKER_TAG} -t zerotier/zerotier:latest --build-arg VERSION=${RELEASE_VERSION} -f Dockerfile.release . --push

View file

@ -10,7 +10,10 @@
* of this software will be governed by version 2.0 of the Apache License. * of this software will be governed by version 2.0 of the Apache License.
*/ */
#include "Metrics.hpp" // clang-format off
#include <prometheus/simpleapi.h>
#include <prometheus/histogram.h>
// clang-format on
namespace prometheus { namespace prometheus {
namespace simpleapi { namespace simpleapi {

View file

@ -12,9 +12,10 @@
#ifndef METRICS_H_ #ifndef METRICS_H_
#define METRICS_H_ #define METRICS_H_
#include <prometheus/gauge.h> // clang-format off
#include <prometheus/histogram.h>
#include <prometheus/simpleapi.h> #include <prometheus/simpleapi.h>
#include <prometheus/histogram.h>
// clang-format on
namespace prometheus { namespace prometheus {
namespace simpleapi { namespace simpleapi {

View file

@ -39,7 +39,10 @@ ONE_OBJS=\
controller/DB.o \ controller/DB.o \
controller/FileDB.o \ controller/FileDB.o \
controller/LFDB.o \ controller/LFDB.o \
controller/CtlUtil.o \
controller/PostgreSQL.o \ controller/PostgreSQL.o \
controller/CV1.o \
controller/CV2.o \
osdep/EthernetTap.o \ osdep/EthernetTap.o \
osdep/ManagedRoute.o \ osdep/ManagedRoute.o \
osdep/Http.o \ osdep/Http.o \

View file

@ -19,9 +19,11 @@
#include <string> #include <string>
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#include <windows.h> // clang-format off
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <windows.h>
// clang-format on
#else #else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>

View file

@ -709,8 +709,8 @@ static void _moonToJson(nlohmann::json& mj, const World& world)
OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", world.id()); OSUtils::ztsnprintf(tmp, sizeof(tmp), "%.16llx", world.id());
mj["id"] = tmp; mj["id"] = tmp;
mj["timestamp"] = world.timestamp(); mj["timestamp"] = world.timestamp();
mj["signature"] = Utils::hex(world.signature().data, ZT_ECC_SIGNATURE_LEN, tmp); mj["signature"] = Utils::hex(world.signature().data, ZT_C25519_SIGNATURE_LEN, tmp);
mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data, ZT_ECC_PUBLIC_KEY_SET_LEN, tmp); mj["updatesMustBeSignedBy"] = Utils::hex(world.updatesMustBeSignedBy().data, ZT_C25519_PUBLIC_KEY_LEN, tmp);
nlohmann::json ra = nlohmann::json::array(); nlohmann::json ra = nlohmann::json::array();
for (std::vector<World::Root>::const_iterator r(world.roots().begin()); r != world.roots().end(); ++r) { for (std::vector<World::Root>::const_iterator r(world.roots().begin()); r != world.roots().end(); ++r) {
nlohmann::json rj; nlohmann::json rj;