6#include <QtCore/QPointer>
20 : timeout(scheduler, context)
48 auto casterConfig =
config;
49 casterConfig.mountpoint.clear();
50 const bool sameCaster = casterConfig == _lastFetchConfig;
53 if (
error.isEmpty() && _attempt && sameCaster) {
54 _sortCoord = sortCoord;
59 if (!
error.isEmpty()) {
64 if (_model->
count() > 0 && _cacheStoredAtUs && sameCaster) {
65 const auto nowUs = _scheduler->
nowUs();
67 qCDebug(NTRIPSourceTableControllerLog) <<
"Source table cache hit, age:"
68 << std::chrono::duration_cast<std::chrono::milliseconds>(
70 _sortCoord = sortCoord;
77 _cacheStoredAtUs.reset();
78 _sortCoord = sortCoord;
80 _lastFetchConfig = casterConfig;
82 if (casterConfig.sendsCredentialsInClear()) {
83 qCWarning(NTRIPSourceTableControllerLog) <<
"Sending source-table credentials without TLS";
95void NTRIPSourceTableController::_startFetch()
97 _attempt = std::make_unique<FetchAttempt>(_scheduler,
this);
99 _attempt->session = session;
107 [
this]() { _finishFetch(tr(
"Response does not contain a valid source table")); });
109 if (
const QString openError = session->open(_lastFetchConfig); !openError.isEmpty()) {
110 _finishFetch(openError);
114void NTRIPSourceTableController::_armFetchTimeout()
119 if (!_attempt->session || !_attempt->session->awaitingErrorBody()) {
120 _finishFetch(tr(
"Source table request timed out"));
125void NTRIPSourceTableController::_readReply(
const QByteArray& bytes)
132 const qsizetype checkedSize = _attempt->body.size();
133 _attempt->body += bytes;
140void NTRIPSourceTableController::_finishFetch(
const QString&
error)
145 const QByteArray body = _attempt->body;
147 if (
error.isEmpty()) {
148 _onSourceTableReceived(QString::fromUtf8(body));
150 _onFetchError(
error);
154void NTRIPSourceTableController::_onSourceTableReceived(
const QString& table)
157 _cacheStoredAtUs = _scheduler->
nowUs();
161void NTRIPSourceTableController::_onFetchError(
const QString&
error)
163 _cacheStoredAtUs.reset();
168void NTRIPSourceTableController::_setFetchState(FetchStatus status,
const QString&
error)
170 const bool statusChanged = std::exchange(_fetchStatus, status) != status;
171 const bool errorChanged = std::exchange(_fetchError,
error) !=
error;
180void NTRIPSourceTableController::_abortFetch()
186 if (_attempt->session) {
187 _attempt->session->retire();
bool ntripSourceTableComplete(QByteArrayView body, qsizetype checkedSize)
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void certificatePinned(const QString &pin)
A newly trusted self-signed certificate, as NTRIPConnectionConfig::pinnedCertificate; precedes the re...
void finished()
The response ended where its HTTP framing allows.
void bodyReceived(const QByteArray &body, qint64 receivedAtMs)
Body bytes, with the scheduler time at which the bytes carrying them arrived.
void responseStarted()
The caster accepted the request; its body follows.
void failed(const NTRIPFailure &failure)
A socket, TLS or HTTP failure, including an error status with the caster's explanation.
void fetch(const NTRIPConnectionConfig &config, const QGeoCoordinate &sortCoord={})
static constexpr std::chrono::milliseconds CACHE_TTL
~NTRIPSourceTableController() override
void fetchStatusChanged()
void certificatePinned(const QString &pin)
A self-signed caster certificate was trusted on first use; the owner persists the pin.
void securityWarningChanged()
static constexpr qint64 MAX_SOURCE_TABLE_BYTES
NTRIPSourceTableController(QObject *parent=nullptr, RuntimeScheduler *scheduler=nullptr)
QAbstractItemModel * mountpointModel() const
static constexpr std::chrono::milliseconds FETCH_TIMEOUT
QString securityWarning() const
Set while the latest fetch sends caster credentials without TLS.
void updateDistances(const QGeoCoordinate &from)
Recompute distances; one dataChanged for DistanceKmRole spans the rows whose distance changed.
void parseSourceTable(const QString &raw, const QGeoCoordinate &from={})
Publish the parsed rows and their distances in a single reset.
virtual quint64 nowUs() const =0
constexpr std::optional< std::chrono::duration< Rep, Period > > age(std::chrono::duration< Rep, Period > timestamp, std::chrono::duration< Rep, Period > now)
Age of timestamp at now, both in the same unit; empty for a missing or future timestamp.
constexpr bool fresh(uint64_t timestampUs, uint64_t nowUs, std::chrono::microseconds lifetime)
Whether a receipt is younger than lifetime.
QString validationError() const
QPointer< NTRIPHttpSession > session
FetchAttempt(RuntimeScheduler *scheduler, QObject *context)