From 663c33475bffd5e1d859a735238245ade4a8262b Mon Sep 17 00:00:00 2001 From: staphen Date: Sun, 30 Jul 2023 10:14:18 -0400 Subject: [PATCH] Introduce function to determine if ZT comms channel to peer is relayed --- 3rdParty/libzt/CMakeLists.txt | 2 +- Source/dvlnet/protocol_zt.cpp | 22 +++++++++++ Source/dvlnet/protocol_zt.h | 1 + Source/dvlnet/zerotier_native.cpp | 65 ++++++++++++++++++++++++------- Source/dvlnet/zerotier_native.h | 4 +- 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/3rdParty/libzt/CMakeLists.txt b/3rdParty/libzt/CMakeLists.txt index e3feb8cd3..76219cefa 100644 --- a/3rdParty/libzt/CMakeLists.txt +++ b/3rdParty/libzt/CMakeLists.txt @@ -5,7 +5,7 @@ set(BUILD_HOST_SELFTEST OFF) include(FetchContent) FetchContent_Declare(libzt GIT_REPOSITORY https://github.com/diasurgical/libzt.git - GIT_TAG d6c6a069a5041a3e89594c447ced3f15d77618b8) + GIT_TAG def49803307920da0ab5b9e9b70b399fdc2943dc) FetchContent_MakeAvailableExcludeFromAll(libzt) if(NOT ANDROID) diff --git a/Source/dvlnet/protocol_zt.cpp b/Source/dvlnet/protocol_zt.cpp index ff50a33e8..43f6c4724 100644 --- a/Source/dvlnet/protocol_zt.cpp +++ b/Source/dvlnet/protocol_zt.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -312,6 +313,27 @@ bool protocol_zt::is_peer_connected(endpoint &peer) return peer_list.count(peer) != 0 && peer_list[peer].fd != -1; } +bool protocol_zt::is_peer_relayed(const endpoint &peer) const +{ + ip6_addr_t address = {}; + IP6_ADDR_PART(&address, 0, peer.addr[0], peer.addr[1], peer.addr[2], peer.addr[3]); + IP6_ADDR_PART(&address, 1, peer.addr[4], peer.addr[5], peer.addr[6], peer.addr[7]); + IP6_ADDR_PART(&address, 2, peer.addr[8], peer.addr[9], peer.addr[10], peer.addr[11]); + IP6_ADDR_PART(&address, 3, peer.addr[12], peer.addr[13], peer.addr[14], peer.addr[15]); + + const u8_t *hwaddr; + if (nd6_get_next_hop_addr_or_queue(netif_default, nullptr, &address, &hwaddr) != ERR_OK) + return true; + + uint64_t mac = hwaddr[0]; + mac = (mac << 8) | hwaddr[1]; + mac = (mac << 8) | hwaddr[2]; + mac = (mac << 8) | hwaddr[3]; + mac = (mac << 8) | hwaddr[4]; + mac = (mac << 8) | hwaddr[5]; + return zerotier_is_relayed(mac); +} + std::string protocol_zt::make_default_gamename() { std::string ret; diff --git a/Source/dvlnet/protocol_zt.h b/Source/dvlnet/protocol_zt.h index 95513bec1..ade771ea1 100644 --- a/Source/dvlnet/protocol_zt.h +++ b/Source/dvlnet/protocol_zt.h @@ -75,6 +75,7 @@ public: bool get_disconnected(endpoint &peer); bool network_online(); bool is_peer_connected(endpoint &peer); + bool is_peer_relayed(const endpoint &peer) const; static std::string make_default_gamename(); private: diff --git a/Source/dvlnet/zerotier_native.cpp b/Source/dvlnet/zerotier_native.cpp index 21696d3d3..82d9c68dd 100644 --- a/Source/dvlnet/zerotier_native.cpp +++ b/Source/dvlnet/zerotier_native.cpp @@ -2,6 +2,7 @@ #include #include +#include #ifdef USE_SDL1 #include "utils/sdl2_to_1_2_backports.h" @@ -38,6 +39,15 @@ namespace net { namespace { +// static constexpr uint64_t zt_earth = 0x8056c2e21c000001; +constexpr uint64_t ZtNetwork = 0xa84ac5c10a7ebb5f; + +std::atomic_bool zt_network_ready(false); +std::atomic_bool zt_node_online(false); +std::atomic_bool zt_joined(false); + +std::unordered_map ztPeerEvents; + #ifdef DVL_ZT_SYMLINK bool HasMultiByteChars(string_view path) { @@ -107,38 +117,48 @@ std::string ToZTCompliantPath(string_view configPath) } #endif -} // namespace - -// static constexpr uint64_t zt_earth = 0x8056c2e21c000001; -static constexpr uint64_t ZtNetwork = 0xa84ac5c10a7ebb5f; - -static std::atomic_bool zt_network_ready(false); -static std::atomic_bool zt_node_online(false); -static std::atomic_bool zt_joined(false); - -static void Callback(void *ptr) +void Callback(void *ptr) { zts_event_msg_t *msg = reinterpret_cast(ptr); - // printf("callback %i\n", msg->eventCode); - if (msg->event_code == ZTS_EVENT_NODE_ONLINE) { + + switch (msg->event_code) { + case ZTS_EVENT_NODE_ONLINE: Log("ZeroTier: ZTS_EVENT_NODE_ONLINE, nodeId={:x}", (unsigned long long)msg->node->node_id); zt_node_online = true; if (!zt_joined) { zts_net_join(ZtNetwork); zt_joined = true; } - } else if (msg->event_code == ZTS_EVENT_NODE_OFFLINE) { + break; + + case ZTS_EVENT_NODE_OFFLINE: Log("ZeroTier: ZTS_EVENT_NODE_OFFLINE"); zt_node_online = false; - } else if (msg->event_code == ZTS_EVENT_NETWORK_READY_IP6) { + break; + + case ZTS_EVENT_NETWORK_READY_IP6: Log("ZeroTier: ZTS_EVENT_NETWORK_READY_IP6, networkId={:x}", (unsigned long long)msg->network->net_id); zt_ip6setup(); zt_network_ready = true; - } else if (msg->event_code == ZTS_EVENT_ADDR_ADDED_IP6) { + break; + + case ZTS_EVENT_ADDR_ADDED_IP6: print_ip6_addr(&(msg->addr->addr)); + break; + + case ZTS_EVENT_PEER_DIRECT: + case ZTS_EVENT_PEER_RELAY: + ztPeerEvents[msg->peer->peer_id] = static_cast(msg->event_code); + break; + + case ZTS_EVENT_PEER_PATH_DEAD: + ztPeerEvents.erase(msg->peer->peer_id); + break; } } +} // namespace + bool zerotier_network_ready() { return zt_network_ready && zt_node_online; @@ -156,5 +176,20 @@ void zerotier_network_start() zts_node_start(); } +bool zerotier_is_relayed(uint64_t mac) +{ + bool isRelayed = true; + if (zts_core_lock_obtain() != ZTS_ERR_OK) + return isRelayed; + zts_peer_info_t peerInfo; + if (zts_core_query_peer_info(ZtNetwork, mac, &peerInfo) == ZTS_ERR_OK) { + auto peerEvent = ztPeerEvents.find(peerInfo.peer_id); + if (peerEvent != ztPeerEvents.end()) + isRelayed = (peerEvent->second == ZTS_EVENT_PEER_RELAY); + } + zts_core_lock_release(); + return isRelayed; +} + } // namespace net } // namespace devilution diff --git a/Source/dvlnet/zerotier_native.h b/Source/dvlnet/zerotier_native.h index 3febbe6ed..48149e16d 100644 --- a/Source/dvlnet/zerotier_native.h +++ b/Source/dvlnet/zerotier_native.h @@ -1,11 +1,13 @@ #pragma once +#include + namespace devilution { namespace net { bool zerotier_network_ready(); void zerotier_network_start(); -void zerotier_network_stop(); +bool zerotier_is_relayed(uint64_t mac); // NOTE: We have patched our libzt to have the corresponding multicast // MAC hardcoded, since libzt is still missing the proper handling.