Matthias Nott
2026-03-25 a7b094a1284fd1fa9c8aaf84598e5ee12ed6041d
fix: cache discovered host to prevent repeated subnet scan floods
1 files modified
changed files
lib/services/mqtt_service.dart patch | view | blame | history
lib/services/mqtt_service.dart
....@@ -44,6 +44,7 @@
4444 ConnectionStatus _status = ConnectionStatus.disconnected;
4545 bool _intentionalClose = false;
4646 String? _clientId;
47
+ String? _lastDiscoveredHost;
4748 StreamSubscription? _updatesSub;
4849
4950 // Message deduplication
....@@ -104,12 +105,15 @@
104105
105106 final clientId = await _getClientId();
106107
107
- // Connection order: local → Bonjour → VPN → remote
108
+ // Connection order: local → cached discovery → Bonjour/scan → VPN → remote
108109 final attempts = <MapEntry<String, int>>[]; // host → timeout ms
109110 if (config.localHost != null && config.localHost!.isNotEmpty) {
110111 attempts.add(MapEntry(config.localHost!, 2500));
111112 }
112
- // Bonjour placeholder — inserted dynamically below
113
+ // Try cached discovered host before scanning again
114
+ if (_lastDiscoveredHost != null) {
115
+ attempts.add(MapEntry(_lastDiscoveredHost!, 3000));
116
+ }
113117 if (config.vpnHost != null && config.vpnHost!.isNotEmpty) {
114118 attempts.add(MapEntry(config.vpnHost!, 3000));
115119 }
....@@ -118,7 +122,6 @@
118122 }
119123 _mqttLog('MQTT: attempts=${attempts.map((e) => e.key).join(", ")} port=${config.port}');
120124
121
- // Try configured local host first
122125 for (final attempt in attempts) {
123126 if (_intentionalClose) return;
124127 _mqttLog('MQTT: trying ${attempt.key}:${config.port}');
....@@ -127,21 +130,22 @@
127130 } catch (e) {
128131 _mqttLog('MQTT: ${attempt.key} error=$e');
129132 }
133
+ }
130134
131
- // After local host fails, try Bonjour discovery before VPN/remote
132
- if (attempt.key == config.localHost && !_intentionalClose) {
133
- _mqttLog('MQTT: trying Bonjour discovery...');
134
- final bonjourHost = await _discoverViaMdns();
135
- if (bonjourHost != null && !_intentionalClose) {
136
- _mqttLog('MQTT: Bonjour found $bonjourHost');
137
- try {
138
- if (await _tryConnect(bonjourHost, clientId, timeout: 3000)) return;
139
- } catch (e) {
140
- _mqttLog('MQTT: Bonjour host $bonjourHost error=$e');
141
- }
142
- } else {
143
- _mqttLog('MQTT: Bonjour discovery returned nothing');
135
+ // All configured hosts failed — try Bonjour/subnet scan (only once, not on retry)
136
+ if (_lastDiscoveredHost == null && !_intentionalClose) {
137
+ _mqttLog('MQTT: trying Bonjour/subnet discovery...');
138
+ final discovered = await _discoverViaMdns();
139
+ if (discovered != null && !_intentionalClose) {
140
+ _lastDiscoveredHost = discovered;
141
+ _mqttLog('MQTT: discovered $discovered, connecting...');
142
+ try {
143
+ if (await _tryConnect(discovered, clientId, timeout: 3000)) return;
144
+ } catch (e) {
145
+ _mqttLog('MQTT: discovered host $discovered error=$e');
144146 }
147
+ } else {
148
+ _mqttLog('MQTT: discovery returned nothing');
145149 }
146150 }
147151