QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
TransportStrategy.cc
Go to the documentation of this file.
1#include "TransportStrategy.h"
2
4#include "RemoteTransport.h"
5
6QGC_LOGGING_CATEGORY(TransportStrategyLog, "Utilities.TransportStrategy")
7
8TransportStrategy::TransportStrategy(QObject* parent) : QObject(parent)
9{
10}
11
13{
14 if (_tcpTransport) {
15 _tcpTransport->close();
16 }
17 if (_udpTransport) {
18 _udpTransport->close();
19 }
20}
21
23{
24 if (_protocol == protocol) {
25 return;
26 }
27 _protocol = protocol;
28 if (_tcpTransport) {
29 _tcpTransport->close();
30 }
31 if (_udpTransport) {
32 _udpTransport->resetFailureCount();
33 }
34 _tcpReconnectMs = kInitialReconnectMs;
35}
36
37void TransportStrategy::setTarget(const QString& host, quint16 port)
38{
39 if (_host == host && _port == port) {
40 return;
41 }
42 _host = host;
43 _port = port;
44 reset();
45}
46
48{
49 if (_tcpTransport) {
50 _tcpTransport->close();
51 _configureTcp();
52 }
53 if (_udpTransport) {
54 _udpTransport->close();
55 _udpTransport->deleteLater();
56 _udpTransport = nullptr;
57 }
58 _tcpReconnectMs = kInitialReconnectMs;
59}
60
61// ---------------------------------------------------------------------------
62// TLS configuration
63// ---------------------------------------------------------------------------
64
66{
67 _tlsEnabled = enabled;
68 if (_tcpTransport) {
69 _tcpTransport->close();
70 _configureTcp();
71 }
72}
73
75{
76 _tlsVerifyPeer = verify;
77 if (_tcpTransport) {
78 _tcpTransport->close();
79 _configureTcp();
80 }
81}
82
83void TransportStrategy::setTlsCaCertificates(const QList<QSslCertificate>& certs)
84{
85 _tlsCaCerts = certs;
86 if (_tcpTransport) {
87 _tcpTransport->setTlsCaCertificates(_tlsCaCerts);
88 }
89}
90
91void TransportStrategy::setTlsClientCertificate(const QSslCertificate& cert, const QSslKey& key)
92{
93 _tlsClientCert = cert;
94 _tlsClientKey = key;
95 if (_tcpTransport) {
96 _tcpTransport->setTlsClientCertificate(_tlsClientCert, _tlsClientKey);
97 }
98}
99
100// ---------------------------------------------------------------------------
101// Transport lifecycle
102// ---------------------------------------------------------------------------
103
104void TransportStrategy::_ensureUdp()
105{
106 if (!_udpTransport) {
107 _udpTransport = new UdpTransport(this);
108 _udpTransport->setTarget(_host, _port);
109 }
110}
111
112void TransportStrategy::_ensureTcp()
113{
114 if (!_tcpTransport) {
115 _tcpTransport = new TcpTransport(this);
116 _configureTcp();
117 (void)connect(_tcpTransport, &TcpTransport::connected, this, &TransportStrategy::_onTcpConnected);
118 (void)connect(_tcpTransport, &TcpTransport::disconnected, this, &TransportStrategy::_onTcpDisconnected);
119 (void)connect(_tcpTransport, &TcpTransport::errorOccurred, this, &TransportStrategy::_onTransportError);
120 }
121}
122
123void TransportStrategy::_configureTcp()
124{
125 if (!_tcpTransport) {
126 return;
127 }
128 _tcpTransport->setTarget(_host, _port);
129 _tcpTransport->setTlsEnabled(_tlsEnabled);
130 _tcpTransport->setTlsVerifyPeer(_tlsVerifyPeer);
131 if (!_tlsCaCerts.isEmpty()) {
132 _tcpTransport->setTlsCaCertificates(_tlsCaCerts);
133 }
134 if (!_tlsClientCert.isNull()) {
135 _tcpTransport->setTlsClientCertificate(_tlsClientCert, _tlsClientKey);
136 }
137}
138
139bool TransportStrategy::_shouldUseTcp() const
140{
141 if (_protocol == Protocol::TCP) {
142 return true;
143 }
144 if (_protocol == Protocol::AutoFallback && _udpTransport &&
145 _udpTransport->failureCount() >= kUdpFailureThreshold) {
146 return true;
147 }
148 return false;
149}
150
151// ---------------------------------------------------------------------------
152// Send
153// ---------------------------------------------------------------------------
154
155quint64 TransportStrategy::send(const QByteArray& data)
156{
157 if (_host.isEmpty() || _port == 0) {
158 return 0;
159 }
160
161 if (_shouldUseTcp()) {
162 _ensureTcp();
163
164 if (!_tcpTransport->isConnected()) {
165 _tcpTransport->connectToHost();
166 _tcpReconnectMs = qMin(_tcpReconnectMs * 2, kMaxReconnectMs);
167 return 0;
168 }
169
170 if (!_tcpTransport->send(data)) {
171 return 0;
172 }
173 // TCP framing adds 4 bytes length prefix
174 return static_cast<quint64>(data.size()) + 4;
175 }
176
177 _ensureUdp();
178 if (!_udpTransport->send(data)) {
179 return 0;
180 }
181 return static_cast<quint64>(data.size());
182}
183
185{
186 if (_shouldUseTcp()) {
187 return _tcpTransport && _tcpTransport->isConnected();
188 }
189 return _udpTransport != nullptr;
190}
191
193{
194 return _tcpTransport && _tcpTransport->isConnected();
195}
196
197// ---------------------------------------------------------------------------
198// Transport callbacks
199// ---------------------------------------------------------------------------
200
201void TransportStrategy::_onTcpConnected()
202{
203 _tcpReconnectMs = kInitialReconnectMs;
204 emit connected();
205}
206
207void TransportStrategy::_onTcpDisconnected()
208{
209 emit disconnected();
210}
211
212void TransportStrategy::_onTransportError(const QString& message)
213{
214 emit errorOccurred(message);
215}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void errorOccurred(const QString &message)
bool send(const QByteArray &data) override
void setTlsCaCertificates(const QList< QSslCertificate > &certs)
void close() override
void setTlsEnabled(bool enabled)
void setTlsVerifyPeer(bool verify)
void setTlsClientCertificate(const QSslCertificate &cert, const QSslKey &key)
bool isConnected() const override
void setTarget(const QString &host, quint16 port)
void setTlsClientCertificate(const QSslCertificate &cert, const QSslKey &key)
void errorOccurred(const QString &message)
void setTarget(const QString &host, quint16 port)
~TransportStrategy() override
Protocol protocol() const
quint16 port() const
void setTlsCaCertificates(const QList< QSslCertificate > &certs)
void setTlsVerifyPeer(bool verify)
quint64 send(const QByteArray &data)
Send pre-formatted payload. Returns bytes sent (0 on failure/pending).
void setTlsEnabled(bool enabled)
bool isConnected() const
Whether the active transport is connected and ready.
QString host() const
void reset()
Reset transports (e.g. after host/port change).
void setProtocol(Protocol protocol)
void resetFailureCount()
int failureCount() const
void close() override
bool send(const QByteArray &data) override
void setTarget(const QString &host, quint16 port)