amnezia-client/client/platforms/windows/daemon/windowstunnellogger.cpp
Mykola Baibuz 5bd8c33a6d
Update Mozilla upstream (#790)
* Update Mozilla upstream
2024-05-08 22:02:02 +01:00

135 lines
3.5 KiB
C++

/* 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 "windowstunnellogger.h"
#include <QDateTime>
#include "leakdetector.h"
#include "logger.h"
/* The ring logger format used by the Wireguard DLL is as follows, assuming
* no padding:
*
* struct {
* uint32_t magic;
* uint32_t index;
* struct {
* uint64_t timestamp;
* char message[512];
* } ring[2048];
* };
*/
constexpr uint32_t RINGLOG_POLL_MSEC = 250;
constexpr uint32_t RINGLOG_MAGIC_HEADER = 0xbadbabe;
constexpr uint32_t RINGLOG_INDEX_OFFSET = 4;
constexpr uint32_t RINGLOG_HEADER_SIZE = 8;
constexpr uint32_t RINGLOG_MAX_ENTRIES = 2048;
constexpr uint32_t RINGLOG_MESSAGE_SIZE = 512;
constexpr uint32_t RINGLOG_TIMESTAMP_SIZE = 8;
constexpr uint32_t RINGLOG_FILE_SIZE =
RINGLOG_HEADER_SIZE +
((RINGLOG_MESSAGE_SIZE + RINGLOG_TIMESTAMP_SIZE) * RINGLOG_MAX_ENTRIES);
namespace {
Logger logger("tunnel.dll");
} // namespace
WindowsTunnelLogger::WindowsTunnelLogger(const QString& filename,
QObject* parent)
: QObject(parent), m_timer(this), m_logfile(filename, this) {
MZ_COUNT_CTOR(WindowsTunnelLogger);
m_startTime = QDateTime::currentMSecsSinceEpoch() * 1000000;
m_logindex = -1;
connect(&m_timer, SIGNAL(timeout()), this, SLOT(timeout()));
m_timer.start(RINGLOG_POLL_MSEC);
}
WindowsTunnelLogger::~WindowsTunnelLogger() {
MZ_COUNT_DTOR(WindowsTunnelLogger);
if (m_logdata) {
timeout();
m_logfile.unmap(m_logdata);
m_logdata = nullptr;
}
}
bool WindowsTunnelLogger::openLogData() {
if (m_logdata) {
return true;
}
if (!m_logfile.open(QIODevice::ReadOnly)) {
return false;
}
m_logdata = m_logfile.map(0, RINGLOG_FILE_SIZE);
if (!m_logdata) {
m_logfile.close();
return false;
}
// Check for a valid magic header
uint32_t magic;
memcpy(&magic, m_logdata, 4);
logger.debug() << "Opening tunnel log file" << m_logfile.fileName();
if (magic != RINGLOG_MAGIC_HEADER) {
logger.error() << "Unexpected magic header:" << QString::number(magic, 16);
m_logfile.unmap(m_logdata);
m_logfile.close();
m_logdata = nullptr;
return false;
}
return true;
}
int WindowsTunnelLogger::nextIndex() {
qint32 value;
memcpy(&value, m_logdata + RINGLOG_INDEX_OFFSET, 4);
return value % RINGLOG_MAX_ENTRIES;
}
void WindowsTunnelLogger::process(int index) {
Q_ASSERT(index >= 0);
Q_ASSERT(index < RINGLOG_MAX_ENTRIES);
size_t offset = static_cast<size_t>(index) *
(RINGLOG_TIMESTAMP_SIZE + RINGLOG_MESSAGE_SIZE);
uchar* data = m_logdata + RINGLOG_HEADER_SIZE + offset;
quint64 timestamp;
memcpy(&timestamp, data, RINGLOG_TIMESTAMP_SIZE);
if (timestamp <= m_startTime) {
return;
}
QByteArray message((const char*)data + RINGLOG_TIMESTAMP_SIZE,
RINGLOG_MESSAGE_SIZE);
int nullIndex = message.indexOf(0x0);
if (nullIndex >= 0) {
message.truncate(nullIndex);
}
logger.info() << QString::fromUtf8(message);
}
void WindowsTunnelLogger::timeout() {
if (!openLogData()) {
return;
}
/* On the first pass, scan all log messages. */
if (m_logindex < 0) {
m_logindex = nextIndex();
process(m_logindex);
m_logindex = (m_logindex + 1) % RINGLOG_MAX_ENTRIES;
}
/* Report new messages. */
while (m_logindex != nextIndex()) {
process(m_logindex);
m_logindex = (m_logindex + 1) % RINGLOG_MAX_ENTRIES;
}
}