18 , _connectTimeoutTask(_scheduler, this)
19 , _dataWatchdogTask(_scheduler, this)
21 _rtcmDecoder.setWhitelist(rtcmWhitelist);
22 qCDebug(NTRIPHttpTransportLog) <<
"RTCM message filter:" << rtcmWhitelist;
23 if (rtcmWhitelist.empty()) {
24 qCDebug(NTRIPHttpTransportLog) <<
"Message filter empty; all RTCM message IDs will be forwarded.";
39 if (
const QString
error = session->
open(_config); !
error.isEmpty()) {
41 _fail({NTRIPError::InvalidConfig,
error});
45 qCWarning(NTRIPHttpTransportLog) <<
"Sending credentials without TLS — data is not encrypted";
47 qCDebug(NTRIPHttpTransportLog) <<
"Connecting to mount" << _config.
mountpoint;
48 _startConnectTimeout();
70 _dataSinceValidFrame =
true;
71 _parseRtcm(body, receivedAtMs);
75 [
this]() { _fail({NTRIPError::ServerDisconnected, tr(
"NTRIP correction stream ended")}); });
79void NTRIPHttpTransport::_stopTimers()
81 _connectTimeoutTask.
cancel();
82 _dataWatchdogTask.
cancel();
85qint64 NTRIPHttpTransport::_nowMs()
const
87 return _scheduler->
nowMs();
90void NTRIPHttpTransport::_startConnectTimeout()
94 if (_session && _session->awaitingErrorBody()) {
97 qCWarning(NTRIPHttpTransportLog) <<
"Connection timeout";
98 _fail({NTRIPError::ConnectionTimeout, tr(
"Connection timeout")});
102void NTRIPHttpTransport::_startDataWatchdog(std::chrono::milliseconds delay)
105 _dataWatchdogTask.
schedule(delay, [
this]() {
106 const std::chrono::milliseconds idle{_nowMs() - _lastValidFrameMs};
109 }
else if (_dataSinceValidFrame) {
110 _fail({NTRIPError::DataWatchdog, tr(
"No valid RTCM corrections received")});
112 const auto secs = std::chrono::duration_cast<std::chrono::seconds>(
DATA_WATCHDOG).count();
113 qCWarning(NTRIPHttpTransportLog) <<
"No data received for" << secs <<
"seconds";
114 _fail({NTRIPError::DataWatchdog, tr(
"No data received for %1 seconds").arg(secs)});
119void NTRIPHttpTransport::_retireSession()
122 if (
const auto session = std::exchange(_session, {})) {
129 return !_stopped && _session == session;
132void NTRIPHttpTransport::_fail(
const NTRIPFailure& failure)
146void NTRIPHttpTransport::_onResponseStarted()
150 _connectTimeoutTask.
cancel();
152 if (!_isCurrent(session)) {
155 _lastValidFrameMs = _nowMs();
156 _dataSinceValidFrame =
false;
160void NTRIPHttpTransport::_parseRtcm(
const QByteArray& buffer, qint64 receivedAtMs)
168 qCWarning(NTRIPHttpTransportLog) <<
"Invalid RTCM frame, dropping message id" << frame.messageId;
172 _lastValidFrameMs = _nowMs();
173 _dataSinceValidFrame =
false;
174 if (
frame.filtered) {
175 qCDebug(NTRIPHttpTransportLog) <<
"Ignoring RTCM" << frame.messageId;
178 qCDebug(NTRIPHttpTransportLog) <<
"RTCM packet id" <<
frame.messageId <<
"len" <<
frame.data.size();
180 return _isCurrent(session);
186 if (_stopped || nmea.isEmpty() || !_session || !_session->isConnected()) {
190 if (!_session->write(nmea)) {
191 _fail({NTRIPError::SocketError, tr(
"Socket did not accept the complete NTRIP write")});
194 qCDebug(NTRIPHttpTransportLog) <<
"Queued NMEA bytes:" << nmea.size();
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void certificatePinned(const QString &pin)
A newly trusted self-signed certificate, as NTRIPConnectionConfig::pinnedCertificate; precedes the re...
QString open(const NTRIPConnectionConfig &config)
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 sendNMEA(const QByteArray &nmea) override
static constexpr std::chrono::milliseconds CONNECT_TIMEOUT
static constexpr std::chrono::milliseconds DATA_WATCHDOG
~NTRIPHttpTransport() override
void correctionFrameReceived(const RTCMDecodedFrame &frame)
A valid frame of a whitelisted message.
void certificatePinned(const QString &pin)
A self-signed caster certificate was trusted on first use; the owner persists the pin.
bool feed(QByteArrayView bytes, qint64 receivedAtMs, Deliver &&deliver)
bool schedule(std::chrono::microseconds delay, RuntimeScheduler::Callback callback)
std::optional< Frame > frame(std::string_view text)
bool sendsCredentialsInClear() const
Credentials go to the caster without TLS.