Browse Source

Introduce DvlNet function to read latency data from providers

pull/8276/head
staphen 9 months ago committed by Anders Jenbo
parent
commit
7564bd0fcb
  1. 5
      Source/dvlnet/abstract_net.h
  2. 8
      Source/dvlnet/base.cpp
  3. 2
      Source/dvlnet/base.h
  4. 11
      Source/dvlnet/base_protocol.h
  5. 5
      Source/dvlnet/cdwrap.cpp
  6. 1
      Source/dvlnet/cdwrap.h
  7. 55
      Source/dvlnet/protocol_zt.cpp
  8. 4
      Source/dvlnet/protocol_zt.h
  9. 12
      Source/dvlnet/zerotier_native.cpp
  10. 1
      Source/dvlnet/zerotier_native.h
  11. 6
      Source/storm/storm_net.cpp
  12. 8
      Source/storm/storm_net.hpp

5
Source/dvlnet/abstract_net.h

@ -56,6 +56,11 @@ public:
return std::vector<GameInfo>();
}
virtual DvlNetLatencies get_latencies(uint8_t playerid)
{
return {};
}
static std::unique_ptr<abstract_net> MakeNet(provider_t provider);
};

8
Source/dvlnet/base.cpp

@ -33,6 +33,14 @@ void base::clear_password()
pktfty = std::make_unique<packet_factory>();
}
DvlNetLatencies base::get_latencies(uint8_t playerid)
{
DvlNetLatencies latencies = abstract_net::get_latencies(playerid);
const PlayerState &playerState = playerStateTable_[playerid];
latencies.echoLatency = playerState.roundTripLatency;
return latencies;
}
void base::RunEventHandler(_SNETEVENT &ev)
{
auto f = registered_handlers[static_cast<event_type>(ev.eventid)];

2
Source/dvlnet/base.h

@ -39,6 +39,8 @@ public:
void setup_password(std::string pw) override;
void clear_password() override;
DvlNetLatencies get_latencies(uint8_t playerid) override;
~base() override = default;
protected:

11
Source/dvlnet/base_protocol.h

@ -37,6 +37,7 @@ public:
bool send_info_request() override;
void clear_gamelist() override;
std::vector<GameInfo> get_gamelist() override;
DvlNetLatencies get_latencies(uint8_t playerid) override;
~base_protocol() override = default;
@ -557,6 +558,16 @@ std::vector<GameInfo> base_protocol<P>::get_gamelist()
return ret;
}
template <class P>
DvlNetLatencies base_protocol<P>::get_latencies(uint8_t playerid)
{
DvlNetLatencies latencies = base::get_latencies(playerid);
Peer &srcPeer = peers[playerid];
latencies.providerLatency = proto.get_latency_to(srcPeer.endpoint);
latencies.isRelayed = proto.is_peer_relayed(srcPeer.endpoint);
return latencies;
}
template <class P>
bool base_protocol<P>::SNetLeaveGame(int type)
{

5
Source/dvlnet/cdwrap.cpp

@ -130,4 +130,9 @@ void cdwrap::clear_password()
return dvlnet_wrap->clear_password();
}
DvlNetLatencies cdwrap::get_latencies(uint8_t playerid)
{
return dvlnet_wrap->get_latencies(playerid);
}
} // namespace devilution::net

1
Source/dvlnet/cdwrap.h

@ -52,6 +52,7 @@ public:
std::vector<GameInfo> get_gamelist() override;
void setup_password(std::string pw) override;
void clear_password() override;
DvlNetLatencies get_latencies(uint8_t playerid) override;
virtual ~cdwrap() = default;
};

55
Source/dvlnet/protocol_zt.cpp

@ -1,5 +1,6 @@
#include "dvlnet/protocol_zt.h"
#include <optional>
#include <random>
#ifdef USE_SDL3
@ -26,6 +27,31 @@
namespace devilution {
namespace net {
namespace {
bool GetMAC(const protocol_zt::endpoint &peer, uint64_t &mac)
{
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 false;
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 true;
}
} // namespace
protocol_zt::protocol_zt()
{
zerotier_network_start();
@ -346,27 +372,22 @@ bool protocol_zt::is_peer_connected(endpoint &peer)
return it != peer_list.end() && it->second.fd != -1;
}
bool protocol_zt::is_peer_relayed(const endpoint &peer) const
std::optional<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];
uint64_t mac;
if (!GetMAC(peer, mac))
return std::nullopt;
return zerotier_is_relayed(mac);
}
std::optional<int> protocol_zt::get_latency_to(const endpoint &peer) const
{
uint64_t mac;
if (!GetMAC(peer, mac))
return std::nullopt;
return zerotier_latency(mac);
}
std::string protocol_zt::make_default_gamename()
{
std::string ret;

4
Source/dvlnet/protocol_zt.h

@ -6,6 +6,7 @@
#include <cstdint>
#include <deque>
#include <exception>
#include <optional>
#include <string>
#include <ankerl/unordered_dense.h>
@ -84,7 +85,8 @@ public:
tl::expected<bool, PacketError> network_online();
tl::expected<bool, PacketError> peers_ready();
bool is_peer_connected(endpoint &peer);
bool is_peer_relayed(const endpoint &peer) const;
std::optional<bool> is_peer_relayed(const endpoint &peer) const;
std::optional<int> get_latency_to(const endpoint &peer) const;
static std::string make_default_gamename();
private:

12
Source/dvlnet/zerotier_native.cpp

@ -211,5 +211,17 @@ bool zerotier_is_relayed(uint64_t mac)
return isRelayed;
}
int zerotier_latency(uint64_t mac)
{
int latency = -1;
if (zts_core_lock_obtain() != ZTS_ERR_OK)
return latency;
zts_peer_info_t peerInfo;
if (zts_core_query_peer_info(ZtNetwork, mac, &peerInfo) == ZTS_ERR_OK)
latency = peerInfo.latency;
zts_core_lock_release();
return latency;
}
} // namespace net
} // namespace devilution

1
Source/dvlnet/zerotier_native.h

@ -9,6 +9,7 @@ bool zerotier_network_ready();
bool zerotier_peers_ready();
void zerotier_network_start();
bool zerotier_is_relayed(uint64_t mac);
int zerotier_latency(uint64_t mac);
// NOTE: We have patched our libzt to have the corresponding multicast
// MAC hardcoded, since libzt is still missing the proper handling.

6
Source/storm/storm_net.cpp

@ -15,6 +15,7 @@
#include "engine/demomode.h"
#include "headless_mode.hpp"
#include "menu.h"
#include "multi.h"
#include "options.h"
#include "utils/stubs.h"
#include "utils/utf8.hpp"
@ -238,4 +239,9 @@ bool DvlNet_IsPublicGame()
return GameIsPublic;
}
DvlNetLatencies DvlNet_GetLatencies(uint8_t playerId)
{
return dvlnet_inst->get_latencies(playerId);
}
} // namespace devilution

8
Source/storm/storm_net.hpp

@ -2,6 +2,7 @@
#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <vector>
@ -42,6 +43,12 @@ struct _SNETEVENT {
size_t databytes; // native-endian
};
struct DvlNetLatencies {
uint32_t echoLatency;
std::optional<int> providerLatency;
std::optional<bool> isRelayed;
};
#define PS_CONNECTED 0x10000
#define PS_TURN_ARRIVED 0x20000
#define PS_ACTIVE 0x40000
@ -138,5 +145,6 @@ std::vector<GameInfo> DvlNet_GetGamelist();
void DvlNet_SetPassword(std::string pw);
void DvlNet_ClearPassword();
bool DvlNet_IsPublicGame();
DvlNetLatencies DvlNet_GetLatencies(uint8_t playerId);
} // namespace devilution

Loading…
Cancel
Save