QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
SigningController.h
Go to the documentation of this file.
1#pragma once
2
3#include <QtCore/QMutex>
4#include <QtCore/QObject>
5#include <QtCore/QString>
6#include <QtCore/QTimer>
7#include <chrono>
8#include <optional>
9
11#include "MAVLinkMessageType.h"
12#include "MAVLinkSigning.h"
13#include "SigningChannel.h"
14#include "SigningFailure.h"
15#include "SigningStatus.h"
16
19class SigningController : public QObject
20{
21 Q_OBJECT
22public:
25
26 Q_PROPERTY(State state READ state NOTIFY stateChanged)
27
28 explicit SigningController(mavlink_channel_t channel, QObject* parent = nullptr);
29 ~SigningController() override;
30
31 State state() const;
32 SigningStatus status() const;
33
34 bool isEnabled() const;
35 QString keyName() const;
36 QString statusText() const;
37
39 [[nodiscard]] std::optional<SigningFailure> tryBeginEnable(uint8_t expectedSysId, const QString& keyName,
40 const MAVLinkSigning::SigningKey& keyBytes);
41
43 [[nodiscard]] std::optional<SigningFailure> tryBeginDisable(uint8_t expectedSysId);
44
47 void cancelPending(const QString& detail = {});
48
49 bool clearSigning();
50
53 const QString& keyNameHint = {});
54
55 const SigningChannel& channel() const { return _channel; }
56
59 bool signOutgoing(mavlink_message_t& message) { return _channel.signOutgoing(message); }
60
61 void recordDetectMiss() { _channel.recordDetectMiss(); }
62
64
66 bool processFrame(bool framingOk, const mavlink_message_t& message);
67
68 void resetBadSigBurst();
69
70 bool wallClockRefreshActiveForTesting() const { return _wallClockRefresh.isActive(); }
71
73 static void setTimeoutForTesting(std::chrono::milliseconds timeout) { _timeoutOverride = timeout; }
74
75signals:
77 void keyAutoDetected(const QString& keyName);
78 void alertRaised(const QString& detail);
79
81 void signingConfirmed(const QString& keyName);
82
85
86private:
87 enum class OpKind : uint8_t
88 {
89 None,
90 Enable,
91 Disable
92 };
93
94 struct PendingOp
95 {
96 OpKind kind = OpKind::None;
97 uint8_t expectedSysId = 0;
98 QString keyName;
100 bool unsignedSeen = false;
101 };
102
103 bool _isPendingLocked() const { return _op.kind != OpKind::None; }
104
106 void _handleFsmFrameLocked(const mavlink_message_t& message);
107 void _confirmLocked();
108 void _failLocked(FailReason reason, const QString& detail, bool cancelled = false);
109 void _clearLocked();
110 void _setOpLocked(PendingOp next);
111 void _completeDisableSuccessLocked();
112 void _onTimeout();
114 void _setWallClockRefresh(bool on);
115
116 SigningChannel _channel;
117 mavlink_channel_t _mavlinkChannel;
120 mutable QRecursiveMutex _fsmMutex;
121 PendingOp _op;
122 std::optional<QGC::AutoSuspendGuard> _autoDetectGuard;
123 QTimer _timeout;
127 QTimer _wallClockRefresh;
128
129 static constexpr uint8_t kBadSignatureAlertThreshold = 3;
130 QGC::EdgeTriggeredCounter<uint8_t> _badSigBurst{kBadSignatureAlertThreshold};
131
132 static constexpr auto kTimeout = std::chrono::seconds(5);
133 static std::chrono::milliseconds _effectiveTimeout()
134 {
135 return _timeoutOverride > std::chrono::milliseconds::zero() ? _timeoutOverride
136 : std::chrono::milliseconds(kTimeout);
137 }
138 static inline std::chrono::milliseconds _timeoutOverride{0};
140 static constexpr auto kWallClockRefreshInterval = std::chrono::seconds(1);
141};
mavlink_channel_t
struct __mavlink_message mavlink_message_t
Owns MAVLink signing state for one channel: signing/streams structs, key hint, and RW lock.
bool signOutgoing(mavlink_message_t &message)
Owns MAVLink signing state and the deferred-confirmation state machine for one LinkInterface.
void signingConfirmed(const QString &keyName)
Emitted exactly once per begin*() on success. keyName is the enabled key, or empty for disable.
static void setTimeoutForTesting(std::chrono::milliseconds timeout)
Test-only override for the vehicle-confirmation timeout, read at each begin*(); zero restores the def...
std::optional< SigningFailure > tryBeginEnable(uint8_t expectedSysId, const QString &keyName, const MAVLinkSigning::SigningKey &keyBytes)
Begin pending-enable. Caller must send SETUP_SIGNING only on nullopt; outcome arrives via signingConf...
std::optional< SigningFailure > tryBeginDisable(uint8_t expectedSysId)
Atomic check-and-commit for disable; same contract as tryBeginEnable.
QString keyName() const
bool initSigningImmediate(QByteArrayView key, MAVLinkSigning::UnsignedAcceptancePolicy policy, const QString &keyNameHint={})
Bypasses the FSM; used by tests and auto-detect. Non-empty keyNameHint seeds the persisted timestamp.
bool processFrame(bool framingOk, const mavlink_message_t &message)
Per-frame entry point; drives burst alerts, auto-detect, and the FSM. Returns true on auto-detect.
QString statusText() const
SigningFailure::Reason FailReason
void cancelPending(const QString &detail={})
void alertRaised(const QString &detail)
~SigningController() override
SigningStatus status() const
void keyAutoDetected(const QString &keyName)
void signingFailed(SigningFailure failure)
Emitted exactly once per begin*() on failure (timeout, init error, cancel, re-entry).
const SigningChannel & channel() const
bool wallClockRefreshActiveForTesting() const
bool signOutgoing(mavlink_message_t &message)
Reason a signing operation failed. Used by SigningController error path and Vehicle::signingFailed.
std::array< uint8_t, kSigningKeySize > SigningKey
std::array avoids QByteArray COW detach so secureZero() actually wipes the bytes.