Skip to content

Commit 3d039bc

Browse files
committed
Address SmartLink reconnect review feedback
1 parent 714ccfd commit 3d039bc

6 files changed

Lines changed: 57 additions & 5 deletions

File tree

src/core/SmartLinkClient.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ void SmartLinkClient::login(const QString& email, const QString& password)
9999

100100
void SmartLinkClient::loginWithRefreshToken(const QString& refreshToken)
101101
{
102+
if (m_authRequestInProgress) {
103+
qCDebug(lcSmartLink) << "SmartLinkClient: Auth0 refresh already in progress";
104+
return;
105+
}
106+
102107
QUrl url(QString("https://%1/oauth/token").arg(AUTH0_DOMAIN));
103108
QNetworkRequest req(url);
104109
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
@@ -110,9 +115,11 @@ void SmartLinkClient::loginWithRefreshToken(const QString& refreshToken)
110115

111116
qCDebug(lcSmartLink) << "SmartLinkClient: Auth0 refresh token login";
112117

118+
m_authRequestInProgress = true;
113119
auto* reply = m_nam.post(req, QJsonDocument(body).toJson());
114120
connect(reply, &QNetworkReply::finished, this, [this, reply] {
115121
reply->deleteLater();
122+
m_authRequestInProgress = false;
116123

117124
if (reply->error() != QNetworkReply::NoError) {
118125
const auto data = reply->readAll();
@@ -223,6 +230,11 @@ void SmartLinkClient::connectToServer()
223230
return;
224231
}
225232

233+
if (m_socket.state() != QAbstractSocket::UnconnectedState) {
234+
qCWarning(lcSmartLink) << "SmartLinkClient: connect requested while socket is not idle";
235+
return;
236+
}
237+
226238
qCDebug(lcSmartLink) << "SmartLinkClient: connecting to" << SMARTLINK_HOST << ":" << SMARTLINK_PORT;
227239

228240
// Standard TLS with certificate validation
@@ -248,6 +260,14 @@ void SmartLinkClient::reconnect()
248260
return;
249261
}
250262

263+
if (m_socket.state() == QAbstractSocket::ClosingState)
264+
m_socket.abort();
265+
266+
if (m_socket.state() != QAbstractSocket::UnconnectedState) {
267+
qCDebug(lcSmartLink) << "SmartLinkClient: reconnect deferred until socket is idle";
268+
return;
269+
}
270+
251271
if (!m_refreshToken.isEmpty()) {
252272
loginWithRefreshToken(m_refreshToken);
253273
return;

src/core/SmartLinkClient.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ private slots:
119119
QString m_idToken;
120120
QString m_refreshToken;
121121
bool m_authenticated{false};
122+
bool m_authRequestInProgress{false};
122123

123124
// SmartLink server TLS connection
124125
// NOTE: m_pingTimer and m_serverConnected must be declared before m_socket

src/core/WanConnection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class WanConnection : public QObject {
2727
~WanConnection() override;
2828

2929
bool isConnected() const { return m_connected; }
30+
bool isSocketIdle() const { return m_socket.state() == QAbstractSocket::UnconnectedState; }
3031
quint32 clientHandle() const { return m_handle; }
3132
QHostAddress radioAddress() const { return m_socket.peerAddress(); }
3233
quint16 localTcpPort() const { return m_socket.localPort(); }

src/gui/MainWindow.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,18 @@ void MainWindow::requestWanReconnect()
708708
if (m_userDisconnected || m_radioModel.isConnected()
709709
|| m_pendingWanRadio.serial.isEmpty()) {
710710
m_wanReconnectTimer.stop();
711+
m_wanReconnectAttemptInProgress = false;
711712
return;
712713
}
713714

714-
m_connPanel->setStatusText("Reconnecting via SmartLink...");
715-
setPanadapterConnectionAnimation(true, "Reconnecting to remote radio...");
715+
if (m_wanReconnectAttemptInProgress) {
716+
m_wanReconnectTimer.start();
717+
return;
718+
}
719+
720+
m_connPanel->setStatusText("Reconnecting via SmartLink…");
721+
setPanadapterConnectionAnimation(true, "Reconnecting to remote radio…");
722+
m_wanReconnectAttemptInProgress = true;
716723

717724
if (!m_smartLink.isConnected()) {
718725
m_smartLink.reconnect();
@@ -1129,6 +1136,7 @@ MainWindow::MainWindow(QWidget* parent)
11291136
this, [this]{
11301137
m_userDisconnected = true;
11311138
m_wanReconnectTimer.stop();
1139+
m_wanReconnectAttemptInProgress = false;
11321140
setPanadapterConnectionAnimation(false);
11331141
auto& s = AppSettings::instance();
11341142
s.remove("LastConnectedRadioSerial");
@@ -1151,6 +1159,7 @@ MainWindow::MainWindow(QWidget* parent)
11511159
}
11521160

11531161
m_wanReconnectTimer.stop();
1162+
m_wanReconnectAttemptInProgress = false;
11541163
m_connPanel->setStatusText("SmartLink sign-in required");
11551164
statusBar()->showMessage("SmartLink reconnect stopped: " + err, 5000);
11561165
setPanadapterConnectionAnimation(false);
@@ -1161,6 +1170,14 @@ MainWindow::MainWindow(QWidget* parent)
11611170
}
11621171
m_connPanel->show();
11631172
});
1173+
connect(&m_smartLink, &SmartLinkClient::serverConnected,
1174+
this, [this] {
1175+
m_wanReconnectAttemptInProgress = false;
1176+
});
1177+
connect(&m_smartLink, &SmartLinkClient::serverDisconnected,
1178+
this, [this] {
1179+
m_wanReconnectAttemptInProgress = false;
1180+
});
11641181

11651182
connect(m_connPanel, &ConnectionPanel::smartLinkLoginRequested,
11661183
this, [this](const QString& email, const QString& pass) {
@@ -1198,6 +1215,7 @@ MainWindow::MainWindow(QWidget* parent)
11981215
connect(&m_smartLink, &SmartLinkClient::connectReady,
11991216
this, [this](const QString& handle, const QString& serial) {
12001217
if (serial != m_pendingWanRadio.serial) return;
1218+
m_wanReconnectAttemptInProgress = false;
12011219
m_connPanel->setStatusText("TLS connecting to radio…");
12021220
setPanadapterConnectionAnimation(true, "Connecting to remote radio…");
12031221
m_wanConnection.connectToRadio(
@@ -1212,6 +1230,7 @@ MainWindow::MainWindow(QWidget* parent)
12121230
connect(&m_wanConnection, &WanConnection::connected, this, [this] {
12131231
qDebug() << "MainWindow: WAN connection established!";
12141232
m_wanReconnectTimer.stop();
1233+
m_wanReconnectAttemptInProgress = false;
12151234
m_connPanel->setStatusText("Connected via SmartLink");
12161235
m_connPanel->setConnected(true);
12171236

@@ -1223,6 +1242,7 @@ MainWindow::MainWindow(QWidget* parent)
12231242
});
12241243
connect(&m_wanConnection, &WanConnection::disconnected, this, [this] {
12251244
qDebug() << "MainWindow: WAN connection lost";
1245+
m_wanReconnectAttemptInProgress = false;
12261246
m_connPanel->setStatusText("SmartLink disconnected");
12271247
m_connPanel->setConnected(false);
12281248
if (m_userDisconnected) {
@@ -4178,6 +4198,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
41784198
// Suppress reconnect dialog during shutdown (#527)
41794199
m_userDisconnected = true;
41804200
m_wanReconnectTimer.stop();
4201+
m_wanReconnectAttemptInProgress = false;
41814202
if (m_reconnectDlg) {
41824203
m_reconnectDlg->close();
41834204
delete m_reconnectDlg;
@@ -7166,6 +7187,7 @@ void MainWindow::onConnectionStateChanged(bool connected)
71667187
const bool reconnectWan = !m_userDisconnected && m_radioModel.isWan()
71677188
&& !m_pendingWanRadio.serial.isEmpty();
71687189
if (reconnectWan && !m_wanReconnectTimer.isActive()) {
7190+
m_wanReconnectAttemptInProgress = false;
71697191
m_wanReconnectTimer.start();
71707192
}
71717193

@@ -7240,6 +7262,7 @@ void MainWindow::onConnectionStateChanged(bool connected)
72407262
connect(dismissBtn, &QPushButton::clicked, this, [this]() {
72417263
m_userDisconnected = true;
72427264
m_wanReconnectTimer.stop();
7265+
m_wanReconnectAttemptInProgress = false;
72437266
setPanadapterConnectionAnimation(false);
72447267
m_reconnectDlg->close();
72457268
m_reconnectDlg->deleteLater();

src/gui/MainWindow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ private slots:
331331
// Pending WAN radio (between requestConnect and connectReady)
332332
WanRadioInfo m_pendingWanRadio;
333333
QTimer m_wanReconnectTimer;
334+
bool m_wanReconnectAttemptInProgress{false};
334335

335336
// Status bar labels (SmartSDR-style)
336337
QLabel* m_connStatusLabel{nullptr}; // hidden, used for connection state logic

src/models/RadioModel.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,9 +659,15 @@ void RadioModel::disconnectFromRadio()
659659
m_reconnectTimer.stop();
660660
m_pingTimer.stop();
661661
if (m_wanConn) {
662-
m_wanConn->disconnect(this); // remove signal connections to prevent duplicates on reconnect (#224)
663-
m_wanConn->disconnectFromRadio();
664-
m_wanConn = nullptr;
662+
WanConnection* wan = m_wanConn;
663+
wan->disconnect(this); // remove stale connections before adding one-shot teardown (#224)
664+
connect(wan, &WanConnection::disconnected, this, [this, wan]() {
665+
if (m_wanConn == wan)
666+
onDisconnected();
667+
}, Qt::SingleShotConnection);
668+
wan->disconnectFromRadio();
669+
if (wan->isSocketIdle() && m_wanConn == wan)
670+
onDisconnected();
665671
} else if (m_connection->isConnected()) {
666672
// Graceful disconnect: remove our stream and wait for the radio reply
667673
// before closing. Self "client disconnect" is rejected by the radio.

0 commit comments

Comments
 (0)