WireGuard for MacOS (#248)
* WireGuard for MacOS * Fix openvpn block-outside-dns
This commit is contained in:
parent
ed5dc7cdfd
commit
35ecb8499d
118 changed files with 5150 additions and 3486 deletions
189
client/mozilla/pinghelper.cpp
Normal file
189
client/mozilla/pinghelper.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "pinghelper.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <cmath>
|
||||
|
||||
#include "dnspingsender.h"
|
||||
#include "leakdetector.h"
|
||||
#include "logger.h"
|
||||
#include "pingsender.h"
|
||||
#include "pingsenderfactory.h"
|
||||
|
||||
// Any X seconds, a new ping.
|
||||
constexpr uint32_t PING_TIMEOUT_SEC = 1;
|
||||
|
||||
// Maximum window size for ping statistics.
|
||||
constexpr int PING_STATS_WINDOW = 32;
|
||||
|
||||
namespace {
|
||||
Logger logger("PingHelper");
|
||||
}
|
||||
|
||||
PingHelper::PingHelper() {
|
||||
MZ_COUNT_CTOR(PingHelper);
|
||||
|
||||
m_sequence = 0;
|
||||
m_pingData.resize(PING_STATS_WINDOW);
|
||||
|
||||
connect(&m_pingTimer, &QTimer::timeout, this, &PingHelper::nextPing);
|
||||
}
|
||||
|
||||
PingHelper::~PingHelper() { MZ_COUNT_DTOR(PingHelper); }
|
||||
|
||||
void PingHelper::start(const QString& serverIpv4Gateway,
|
||||
const QString& deviceIpv4Address) {
|
||||
logger.debug() << "PingHelper activated for server:"
|
||||
<< logger.sensitive(serverIpv4Gateway);
|
||||
|
||||
m_gateway = QHostAddress(serverIpv4Gateway);
|
||||
m_source = QHostAddress(deviceIpv4Address.section('/', 0, 0));
|
||||
m_pingSender = PingSenderFactory::create(m_source, this);
|
||||
|
||||
// Some platforms require root access to send and receive ICMP pings. If
|
||||
// we happen to be on one of these unlucky devices, create a DnsPingSender
|
||||
// instead.
|
||||
if (!m_pingSender->isValid()) {
|
||||
delete m_pingSender;
|
||||
m_pingSender = new DnsPingSender(m_source, this);
|
||||
}
|
||||
|
||||
connect(m_pingSender, &PingSender::recvPing, this, &PingHelper::pingReceived,
|
||||
Qt::QueuedConnection);
|
||||
connect(m_pingSender, &PingSender::criticalPingError, this,
|
||||
[]() { logger.info() << "Encountered Unrecoverable ping error"; });
|
||||
|
||||
// Reset the ping statistics
|
||||
m_sequence = 0;
|
||||
for (int i = 0; i < PING_STATS_WINDOW; i++) {
|
||||
m_pingData[i].timestamp = -1;
|
||||
m_pingData[i].latency = -1;
|
||||
m_pingData[i].sequence = 0;
|
||||
}
|
||||
|
||||
m_pingTimer.start(PING_TIMEOUT_SEC * 1000);
|
||||
}
|
||||
|
||||
void PingHelper::stop() {
|
||||
logger.debug() << "PingHelper deactivated";
|
||||
|
||||
if (m_pingSender) {
|
||||
delete m_pingSender;
|
||||
m_pingSender = nullptr;
|
||||
}
|
||||
|
||||
m_pingTimer.stop();
|
||||
}
|
||||
|
||||
void PingHelper::nextPing() {
|
||||
#ifdef MZ_DEBUG
|
||||
logger.debug() << "Sending ping seq:" << m_sequence;
|
||||
#endif
|
||||
|
||||
// The ICMP sequence number is used to match replies with their originating
|
||||
// request, and serves as an index into the circular buffer. Overflows of
|
||||
// the sequence number acceptable.
|
||||
int index = m_sequence % PING_STATS_WINDOW;
|
||||
m_pingData[index].timestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
m_pingData[index].latency = -1;
|
||||
m_pingData[index].sequence = m_sequence;
|
||||
m_pingSender->sendPing(m_gateway, m_sequence);
|
||||
|
||||
m_sequence++;
|
||||
}
|
||||
|
||||
void PingHelper::pingReceived(quint16 sequence) {
|
||||
int index = sequence % PING_STATS_WINDOW;
|
||||
if (m_pingData[index].sequence == sequence) {
|
||||
qint64 sendTime = m_pingData[index].timestamp;
|
||||
m_pingData[index].latency = QDateTime::currentMSecsSinceEpoch() - sendTime;
|
||||
emit pingSentAndReceived(m_pingData[index].latency);
|
||||
#ifdef MZ_DEBUG
|
||||
logger.debug() << "Ping answer received seq:" << sequence
|
||||
<< "avg:" << latency()
|
||||
<< "loss:" << QString("%1%").arg(loss() * 100.0)
|
||||
<< "stddev:" << stddev();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint PingHelper::latency() const {
|
||||
int recvCount = 0;
|
||||
qint64 totalMsec = 0;
|
||||
|
||||
for (const PingSendData& data : m_pingData) {
|
||||
if (data.latency < 0) {
|
||||
continue;
|
||||
}
|
||||
recvCount++;
|
||||
totalMsec += data.latency;
|
||||
}
|
||||
|
||||
if (recvCount <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Add half the denominator to produce nearest-integer rounding.
|
||||
totalMsec += recvCount / 2;
|
||||
return static_cast<uint>(totalMsec / recvCount);
|
||||
}
|
||||
|
||||
uint PingHelper::stddev() const {
|
||||
int recvCount = 0;
|
||||
qint64 totalVariance = 0;
|
||||
uint average = PingHelper::latency();
|
||||
|
||||
for (const PingSendData& data : m_pingData) {
|
||||
if (data.latency < 0) {
|
||||
continue;
|
||||
}
|
||||
recvCount++;
|
||||
totalVariance += (average - data.latency) * (average - data.latency);
|
||||
}
|
||||
|
||||
if (recvCount <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return std::sqrt((double)totalVariance / recvCount);
|
||||
}
|
||||
|
||||
uint PingHelper::maximum() const {
|
||||
uint maxRtt = 0;
|
||||
|
||||
for (const PingSendData& data : m_pingData) {
|
||||
if (data.latency < 0) {
|
||||
continue;
|
||||
}
|
||||
if (data.latency > maxRtt &&
|
||||
data.latency < std::numeric_limits<uint>::max()) {
|
||||
maxRtt = static_cast<uint>(data.latency);
|
||||
}
|
||||
}
|
||||
return maxRtt;
|
||||
}
|
||||
|
||||
double PingHelper::loss() const {
|
||||
int sendCount = 0;
|
||||
int recvCount = 0;
|
||||
// Don't count pings that are possibly still in flight as losses.
|
||||
qint64 sendBefore =
|
||||
QDateTime::currentMSecsSinceEpoch() - (PING_TIMEOUT_SEC * 1000);
|
||||
|
||||
for (const PingSendData& data : m_pingData) {
|
||||
if (data.latency >= 0) {
|
||||
recvCount++;
|
||||
sendCount++;
|
||||
} else if ((data.timestamp > 0) && (data.timestamp < sendBefore)) {
|
||||
sendCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendCount <= 0) {
|
||||
return 0.0;
|
||||
}
|
||||
return (double)(sendCount - recvCount) / PING_STATS_WINDOW;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue