c9cdae001 fix(toxav): remove extra copy of video frame on encode 4f6d4546b test: Improve the fake network library. a2581e700 refactor(toxcore): generate `Friend_Request` and `Dht_Nodes_Response` 2aaa11770 refactor(toxcore): use Tox_Memory in generated events 5c367452b test(toxcore): fix incorrect mutex in tox_scenario_get_time 8f92e710f perf: Add a timed limit of number of cookie requests. 695b6417a test: Add some more simulated network support. 815ae9ce9 test(toxcore): fix thread-safety in scenario framework 6d85c754e test(toxcore): add unit tests for net_crypto 9c22e79cc test(support): add SimulatedEnvironment for deterministic testing f34fcb195 chore: Update windows Dockerfile to debian stable (trixie). ece0e8980 fix(group_moderation): allow validating unsorted sanction list signatures a4fa754d7 refactor: rename struct Packet to struct Net_Packet d6f330f85 cleanup: Fix some warnings from coverity. e206bffa2 fix(group_chats): fix sync packets reverting topics 0e4715598 test: Add new scenario testing framework. 668291f44 refactor(toxcore): decouple Network_Funcs from sockaddr via IP_Port fc4396cef fix: potential division by zero in toxav and unsafe hex parsing 8e8b352ab refactor: Add nullable annotations to struct members. 7740bb421 refactor: decouple net_crypto from DHT 1936d4296 test: add benchmark for toxav audio and video 46bfdc2df fix: correct printf format specifiers for unsigned integers REVERT: 1828c5356 fix(toxav): remove extra copy of video frame on encode git-subtree-dir: external/toxcore/c-toxcore git-subtree-split: c9cdae001341e701fca980c9bb9febfeb95d2902
146 lines
4.0 KiB
C++
146 lines
4.0 KiB
C++
#include "network_universe.hh"
|
|
|
|
#include <cstring>
|
|
#include <iostream>
|
|
|
|
#include "fake_sockets.hh"
|
|
|
|
namespace tox::test {
|
|
|
|
bool NetworkUniverse::IP_Port_Key::operator<(const IP_Port_Key &other) const
|
|
{
|
|
if (port != other.port)
|
|
return port < other.port;
|
|
if (ip.family.value != other.ip.family.value)
|
|
return ip.family.value < other.ip.family.value;
|
|
|
|
if (net_family_is_ipv4(ip.family)) {
|
|
return ip.ip.v4.uint32 < other.ip.ip.v4.uint32;
|
|
}
|
|
|
|
return std::memcmp(&ip.ip.v6, &other.ip.ip.v6, sizeof(ip.ip.v6)) < 0;
|
|
}
|
|
|
|
NetworkUniverse::NetworkUniverse() { }
|
|
NetworkUniverse::~NetworkUniverse() { }
|
|
|
|
bool NetworkUniverse::bind_udp(IP ip, uint16_t port, FakeUdpSocket *socket)
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
IP_Port_Key key{ip, port};
|
|
if (udp_bindings_.count(key))
|
|
return false;
|
|
udp_bindings_[key] = socket;
|
|
return true;
|
|
}
|
|
|
|
void NetworkUniverse::unbind_udp(IP ip, uint16_t port)
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
udp_bindings_.erase({ip, port});
|
|
}
|
|
|
|
bool NetworkUniverse::bind_tcp(IP ip, uint16_t port, FakeTcpSocket *socket)
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
tcp_bindings_.insert({{ip, port}, socket});
|
|
return true;
|
|
}
|
|
|
|
void NetworkUniverse::unbind_tcp(IP ip, uint16_t port, FakeTcpSocket *socket)
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
auto range = tcp_bindings_.equal_range({ip, port});
|
|
for (auto it = range.first; it != range.second; ++it) {
|
|
if (it->second == socket) {
|
|
tcp_bindings_.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetworkUniverse::send_packet(Packet p)
|
|
{
|
|
// Apply filters
|
|
for (const auto &filter : filters_) {
|
|
if (!filter(p))
|
|
return;
|
|
}
|
|
|
|
// Notify observers
|
|
for (const auto &observer : observers_) {
|
|
observer(p);
|
|
}
|
|
|
|
p.delivery_time += global_latency_ms_;
|
|
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
event_queue_.push(std::move(p));
|
|
}
|
|
|
|
void NetworkUniverse::process_events(uint64_t current_time_ms)
|
|
{
|
|
while (true) {
|
|
Packet p;
|
|
std::vector<FakeTcpSocket *> tcp_targets;
|
|
FakeUdpSocket *udp_target = nullptr;
|
|
bool has_packet = false;
|
|
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
if (!event_queue_.empty() && event_queue_.top().delivery_time <= current_time_ms) {
|
|
p = event_queue_.top();
|
|
event_queue_.pop();
|
|
has_packet = true;
|
|
|
|
if (p.is_tcp) {
|
|
auto range = tcp_bindings_.equal_range({p.to.ip, net_ntohs(p.to.port)});
|
|
for (auto it = range.first; it != range.second; ++it) {
|
|
tcp_targets.push_back(it->second);
|
|
}
|
|
} else {
|
|
if (udp_bindings_.count({p.to.ip, net_ntohs(p.to.port)})) {
|
|
udp_target = udp_bindings_[{p.to.ip, net_ntohs(p.to.port)}];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!has_packet) {
|
|
break;
|
|
}
|
|
|
|
if (p.is_tcp) {
|
|
for (auto *it : tcp_targets) {
|
|
it->handle_packet(p);
|
|
}
|
|
} else {
|
|
if (udp_target) {
|
|
udp_target->push_packet(std::move(p.data), p.from);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetworkUniverse::set_latency(uint64_t ms) { global_latency_ms_ = ms; }
|
|
|
|
void NetworkUniverse::set_verbose(bool verbose) { verbose_ = verbose; }
|
|
|
|
bool NetworkUniverse::is_verbose() const { return verbose_; }
|
|
|
|
void NetworkUniverse::add_filter(PacketFilter filter) { filters_.push_back(std::move(filter)); }
|
|
|
|
void NetworkUniverse::add_observer(PacketSink sink) { observers_.push_back(std::move(sink)); }
|
|
|
|
uint16_t NetworkUniverse::find_free_port(IP ip, uint16_t start)
|
|
{
|
|
std::lock_guard<std::recursive_mutex> lock(mutex_);
|
|
for (uint16_t port = start; port < 65535; ++port) {
|
|
if (!udp_bindings_.count({ip, port}))
|
|
return port;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
} // namespace tox::test
|