Socket null handling (#1610)

* return null if in connection failure state * reconnect on connection failure * better connection handling * probably not necessary but just incase * connection handling updates * add cancelOnError: true

Matthew Fosse committed Aug 17, 2024 at 19:28 UTC 7c9b72483a66e113db6fee8c23d3b8616c76c41f
2 files changed +40 -36
cw_bitcoin/lib/electrum.dart
+31 -23
@@ -66,6 +66,7 @@ class ElectrumClient {
66
67 try {
68 await socket?.close();
69 + socket = null;
70 } catch (_) {}
71
72 try {
@@ -90,33 +91,40 @@ class ElectrumClient {
91 }
92 _setConnectionStatus(ConnectionStatus.connected);
93
93 - socket!.listen((Uint8List event) {
94 - try {
95 - final msg = utf8.decode(event.toList());
96 - final messagesList = msg.split("\n");
97 - for (var message in messagesList) {
98 - if (message.isEmpty) {
99 - continue;
94 + socket!.listen(
95 + (Uint8List event) {
96 + try {
97 + final msg = utf8.decode(event.toList());
98 + final messagesList = msg.split("\n");
99 + for (var message in messagesList) {
100 + if (message.isEmpty) {
101 + continue;
102 + }
103 + _parseResponse(message);
104 }
101 - _parseResponse(message);
105 + } catch (e) {
106 + print(e.toString());
107 }
103 - } catch (e) {
104 - print(e.toString());
105 - }
106 - }, onError: (Object error) {
107 - final errorMsg = error.toString();
108 - print(errorMsg);
109 - unterminatedString = '';
108 + },
109 + onError: (Object error) {
110 + socket = null;
111 + final errorMsg = error.toString();
112 + print(errorMsg);
113 + unterminatedString = '';
114
111 - final currentHost = socket?.address.host;
112 - final isErrorForCurrentHost = errorMsg.contains(" ${currentHost} ");
115 + final currentHost = socket?.address.host;
116 + final isErrorForCurrentHost = errorMsg.contains(" ${currentHost} ");
117
114 - if (currentHost != null && isErrorForCurrentHost)
115 - _setConnectionStatus(ConnectionStatus.failed);
116 - }, onDone: () {
117 - unterminatedString = '';
118 - if (host == socket?.address.host) _setConnectionStatus(ConnectionStatus.disconnected);
119 - });
118 + if (currentHost != null && isErrorForCurrentHost)
119 + _setConnectionStatus(ConnectionStatus.failed);
120 + },
121 + onDone: () {
122 + socket = null;
123 + unterminatedString = '';
124 + if (host == socket?.address.host) _setConnectionStatus(ConnectionStatus.disconnected);
125 + },
126 + cancelOnError: true,
127 + );
128
129 keepAlive();
130 }
cw_bitcoin/lib/electrum_wallet.dart
+9 -13
@@ -218,10 +218,7 @@ abstract class ElectrumWalletBase
218 if (electrumClient.isConnected) {
219 syncStatus = SyncedSyncStatus();
220 } else {
221 - if (electrumClient.uri != null) {
222 - await electrumClient.connectToUri(electrumClient.uri!, useSSL: electrumClient.useSSL);
223 - startSync();
224 - }
221 + syncStatus = NotConnectedSyncStatus();
222 }
223 }
224 }
@@ -265,6 +262,7 @@ abstract class ElectrumWalletBase
262 Future<Isolate>? _isolate;
263
264 void Function(FlutterErrorDetails)? _onError;
265 + Timer? _reconnectTimer;
266 Timer? _autoSaveTimer;
267 static const int _autoSaveInterval = 30;
268
@@ -1980,13 +1978,6 @@ abstract class ElectrumWalletBase
1978 break;
1979 case ConnectionStatus.failed:
1980 syncStatus = LostConnectionSyncStatus();
1983 - // wait for 5 seconds and then try to reconnect:
1984 - Future.delayed(Duration(seconds: 5), () {
1985 - electrumClient.connectToUri(
1986 - node!.uri,
1987 - useSSL: node!.useSSL ?? false,
1988 - );
1989 - });
1981 break;
1982 case ConnectionStatus.connecting:
1983 syncStatus = ConnectingSyncStatus();
@@ -1996,7 +1987,11 @@ abstract class ElectrumWalletBase
1987 }
1988
1989 void _syncStatusReaction(SyncStatus syncStatus) async {
1999 - if (syncStatus is NotConnectedSyncStatus) {
1990 + if (syncStatus is SyncingSyncStatus) {
1991 + return;
1992 + }
1993 +
1994 + if (syncStatus is NotConnectedSyncStatus || syncStatus is LostConnectionSyncStatus) {
1995 // Needs to re-subscribe to all scripthashes when reconnected
1996 _scripthashesUpdateSubject = {};
1997
@@ -2004,7 +1999,8 @@ abstract class ElectrumWalletBase
1999
2000 _isTryingToConnect = true;
2001
2007 - Future.delayed(Duration(seconds: 10), () {
2002 + _reconnectTimer?.cancel();
2003 + _reconnectTimer = Timer(Duration(seconds: 10), () {
2004 if (this.syncStatus is! SyncedSyncStatus && this.syncStatus is! SyncedTipSyncStatus) {
2005 this.electrumClient.connectToUri(
2006 node!.uri,