Skip to content
API Documentation
BastionGuard™
network_quality.hpp
Go to the documentation of this file.
1/*
2 * BastionGuard™
3 * Copyright (C) 2025–2026 Calogero Scarnà
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 *
17 * BastionGuard™ is a trademark of Calogero Scarnà.
18 * The BastionGuard™ name and branding are not licensed under the GPL.
19 */
20
21#pragma once
22#include <atomic>
23#include <string>
24#include <cmath>
25#include <algorithm>
26
27
28struct NetQuality {
29 std::atomic<double> ewma_rtt_ms{50.0};
30 std::atomic<double> ewma_loss{0.0};
31 std::atomic<int> samples{3};
32
33
34 void update_sample(double rtt_ms, bool success) {
35 const double alpha = 0.55;
36 int s = samples.fetch_add(1, std::memory_order_relaxed) + 1;
37
38 double prev_rtt = ewma_rtt_ms.load(std::memory_order_relaxed);
39 double prev_loss = ewma_loss.load(std::memory_order_relaxed);
40
41
42 rtt_ms = std::clamp(rtt_ms, 1.0, 2000.0);
43
44 double new_rtt = alpha * rtt_ms + (1.0 - alpha) * prev_rtt;
45 double new_loss = alpha * (success ? 0.0 : 1.0) + (1.0 - alpha) * prev_loss;
46
47 ewma_rtt_ms.store(new_rtt, std::memory_order_relaxed);
48 ewma_loss.store(new_loss, std::memory_order_relaxed);
49 }
50
51
52 std::string classify_network() const {
53 double rtt = ewma_rtt_ms.load(std::memory_order_relaxed);
54 double loss = ewma_loss.load(std::memory_order_relaxed);
55
56 if (samples.load(std::memory_order_relaxed) < 3)
57 return "bootstrap";
58
59 if (rtt < 25.0 && loss < 0.005)
60 return "fiber-ftth";
61 if (rtt < 50.0 && loss < 0.008)
62 return "ethernet";
63 if (rtt < 120.0 && loss < 0.015)
64 return "wifi";
65 if (rtt < 200.0 && loss < 0.03)
66 return "dsl/adsl";
67 if (rtt < 400.0 && loss < 0.05)
68 return "fwa-4g";
69 if (rtt < 700.0 && loss < 0.08)
70 return "5g";
71 return "unstable";
72 }
73
74
76 std::string net = classify_network();
77 if (net == "fiber-ftth") return 60;
78 if (net == "ethernet") return 80;
79 if (net == "wifi") return 120;
80 if (net == "dsl/adsl") return 160;
81 if (net == "fwa-4g") return 200;
82 if (net == "5g") return 150;
83 if (net == "bootstrap") return 100;
84 return 250;
85 }
86
87
89 std::string net = classify_network();
90 if (net == "fiber-ftth") return 400;
91 if (net == "ethernet") return 600;
92 if (net == "wifi") return 900;
93 if (net == "dsl/adsl") return 1200;
94 if (net == "fwa-4g") return 1500;
95 if (net == "5g") return 1100;
96 if (net == "bootstrap") return 800;
97 return 1800;
98 }
99
100
101 bool is_mobile_like() const {
102 double rtt = ewma_rtt_ms.load(std::memory_order_relaxed);
103 double loss = ewma_loss.load(std::memory_order_relaxed);
104 return (rtt > 250.0) || (loss > 0.05);
105 }
106
107
108 double rtt_ms() const { return ewma_rtt_ms.load(std::memory_order_relaxed); }
109 double loss() const { return ewma_loss.load(std::memory_order_relaxed); }
110};
111
112
NetQuality g_net_quality
int recommended_https_timeout() const
std::string classify_network() const
std::atomic< int > samples
std::atomic< double > ewma_rtt_ms
bool is_mobile_like() const
double loss() const
double rtt_ms() const
void update_sample(double rtt_ms, bool success)
std::atomic< double > ewma_loss
int recommended_dns_timeout() const