Compare commits
No commits in common. "6d9010b11c73037725ee511785b5a67cbfa702ee" and "988db718a2269df6a5779fb093586fdebc9c74cf" have entirely different histories.
6d9010b11c
...
988db718a2
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,6 +10,3 @@ build/
|
|||||||
# Omit committing pubspec.lock for library packages; see
|
# Omit committing pubspec.lock for library packages; see
|
||||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
|
|
||||||
# Omit pubspec override files generated by melos
|
|
||||||
**/pubspec_overrides.yaml
|
|
||||||
|
@ -16,10 +16,10 @@ dependencies:
|
|||||||
version: 0.1.4+1
|
version: 0.1.4+1
|
||||||
moxxmpp:
|
moxxmpp:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
version: 0.1.2+2
|
version: 0.1.2+1
|
||||||
moxxmpp_socket_tcp:
|
moxxmpp_socket_tcp:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
version: 0.1.2+2
|
version: 0.1.2+1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -1 +0,0 @@
|
|||||||
pubspec_overrides.yaml
|
|
@ -1,7 +1,3 @@
|
|||||||
## 0.1.2+2
|
|
||||||
|
|
||||||
- **FIX**: Fix reconnections when the connection is awaited.
|
|
||||||
|
|
||||||
## 0.1.2+1
|
## 0.1.2+1
|
||||||
|
|
||||||
- **FIX**: A certificate rejection does not crash the connection.
|
- **FIX**: A certificate rejection does not crash the connection.
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
import 'package:logging/logging.dart';
|
|
||||||
import 'package:moxxmpp/moxxmpp.dart';
|
|
||||||
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
|
|
||||||
import 'package:test/test.dart';
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
Logger.root.level = Level.ALL;
|
|
||||||
Logger.root.onRecord.listen((record) {
|
|
||||||
print('${record.level.name}: ${record.time}: ${record.message}');
|
|
||||||
});
|
|
||||||
final log = Logger('FailureReconnectionTest');
|
|
||||||
|
|
||||||
test('Failing an awaited connection', () async {
|
|
||||||
var errors = 0;
|
|
||||||
final connection = XmppConnection(
|
|
||||||
TestingSleepReconnectionPolicy(10),
|
|
||||||
TCPSocketWrapper(false),
|
|
||||||
);
|
|
||||||
connection.registerFeatureNegotiators([
|
|
||||||
StartTlsNegotiator(),
|
|
||||||
]);
|
|
||||||
connection.registerManagers([
|
|
||||||
DiscoManager(),
|
|
||||||
RosterManager(),
|
|
||||||
PingManager(),
|
|
||||||
MessageManager(),
|
|
||||||
PresenceManager('http://moxxmpp.example'),
|
|
||||||
]);
|
|
||||||
connection.asBroadcastStream().listen((event) {
|
|
||||||
if (event is ConnectionStateChangedEvent) {
|
|
||||||
if (event.state == XmppConnectionState.error) {
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connection.setConnectionSettings(
|
|
||||||
ConnectionSettings(
|
|
||||||
jid: JID.fromString('testuser@no-sasl.badxmpp.eu'),
|
|
||||||
password: 'abc123',
|
|
||||||
useDirectTLS: true,
|
|
||||||
allowPlainAuth: true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = await connection.connectAwaitable();
|
|
||||||
log.info('Connection failed as expected');
|
|
||||||
expect(result.success, false);
|
|
||||||
expect(errors, 1);
|
|
||||||
|
|
||||||
log.info('Waiting 20 seconds for unexpected reconnections');
|
|
||||||
await Future.delayed(const Duration(seconds: 20));
|
|
||||||
expect(errors, 1);
|
|
||||||
}, timeout: Timeout.factor(2));
|
|
||||||
}
|
|
@ -163,8 +163,6 @@ class XmppConnection {
|
|||||||
/// Completers for certain actions
|
/// Completers for certain actions
|
||||||
// ignore: use_late_for_private_fields_and_variables
|
// ignore: use_late_for_private_fields_and_variables
|
||||||
Completer<XmppConnectionResult>? _connectionCompleter;
|
Completer<XmppConnectionResult>? _connectionCompleter;
|
||||||
/// Controls whether an XmppSocketClosureEvent triggers a reconnection.
|
|
||||||
bool _socketClosureTriggersReconnect = true;
|
|
||||||
|
|
||||||
/// Negotiators
|
/// Negotiators
|
||||||
final Map<String, XmppFeatureNegotiatorBase> _featureNegotiators;
|
final Map<String, XmppFeatureNegotiatorBase> _featureNegotiators;
|
||||||
@ -352,18 +350,8 @@ class XmppConnection {
|
|||||||
_log.severe('handleError: Called with null');
|
_log.severe('handleError: Called with null');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whenever we encounter an error that would trigger a reconnection attempt while
|
// TODO(Unknown): This may be too harsh for every error
|
||||||
// the connection result is being awaited, don't attempt a reconnection but instead
|
await _setConnectionState(XmppConnectionState.notConnected);
|
||||||
// try to gracefully disconnect.
|
|
||||||
if (_connectionCompleter != null) {
|
|
||||||
_log.info('Not triggering reconnection since connection result is being awaited');
|
|
||||||
await _disconnect(triggeredByUser: false, state: XmppConnectionState.error);
|
|
||||||
_connectionCompleter?.complete(const XmppConnectionResult(false));
|
|
||||||
_connectionCompleter = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _setConnectionState(XmppConnectionState.error);
|
|
||||||
await _reconnectionPolicy.onFailure();
|
await _reconnectionPolicy.onFailure();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,12 +360,8 @@ class XmppConnection {
|
|||||||
if (event is XmppSocketErrorEvent) {
|
if (event is XmppSocketErrorEvent) {
|
||||||
await handleError(event.error);
|
await handleError(event.error);
|
||||||
} else if (event is XmppSocketClosureEvent) {
|
} else if (event is XmppSocketClosureEvent) {
|
||||||
if (_socketClosureTriggersReconnect) {
|
|
||||||
_log.fine('Received XmppSocketClosureEvent. Reconnecting...');
|
_log.fine('Received XmppSocketClosureEvent. Reconnecting...');
|
||||||
await _reconnectionPolicy.onFailure();
|
await _reconnectionPolicy.onFailure();
|
||||||
} else {
|
|
||||||
_log.fine('Received XmppSocketClosureEvent. No reconnection attempt since _socketClosureTriggersReconnect is false...');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -814,7 +798,13 @@ class XmppConnection {
|
|||||||
await _onNegotiationsDone();
|
await _onNegotiationsDone();
|
||||||
} else if (_currentNegotiator!.state == NegotiatorState.error) {
|
} else if (_currentNegotiator!.state == NegotiatorState.error) {
|
||||||
_log.severe('Negotiator returned an error');
|
_log.severe('Negotiator returned an error');
|
||||||
await handleError(null);
|
|
||||||
|
_updateRoutingState(RoutingState.error);
|
||||||
|
await _setConnectionState(XmppConnectionState.error);
|
||||||
|
_connectionCompleter?.complete(const XmppConnectionResult(false));
|
||||||
|
_connectionCompleter = null;
|
||||||
|
|
||||||
|
_closeSocket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -975,31 +965,16 @@ class XmppConnection {
|
|||||||
|
|
||||||
/// Attempt to gracefully close the session
|
/// Attempt to gracefully close the session
|
||||||
Future<void> disconnect() async {
|
Future<void> disconnect() async {
|
||||||
await _disconnect(state: XmppConnectionState.notConnected);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _disconnect({required XmppConnectionState state, bool triggeredByUser = true}) async {
|
|
||||||
_reconnectionPolicy.setShouldReconnect(false);
|
_reconnectionPolicy.setShouldReconnect(false);
|
||||||
_socketClosureTriggersReconnect = false;
|
|
||||||
|
|
||||||
if (triggeredByUser) {
|
|
||||||
getPresenceManager().sendUnavailablePresence();
|
getPresenceManager().sendUnavailablePresence();
|
||||||
}
|
|
||||||
|
|
||||||
_socket.prepareDisconnect();
|
_socket.prepareDisconnect();
|
||||||
|
|
||||||
if (triggeredByUser) {
|
|
||||||
sendRawString('</stream:stream>');
|
sendRawString('</stream:stream>');
|
||||||
}
|
await _setConnectionState(XmppConnectionState.notConnected);
|
||||||
|
|
||||||
await _setConnectionState(state);
|
|
||||||
_socket.close();
|
_socket.close();
|
||||||
|
|
||||||
if (triggeredByUser) {
|
|
||||||
// Clear Stream Management state, if available
|
// Clear Stream Management state, if available
|
||||||
await getStreamManagementManager()?.resetState();
|
await getStreamManagementManager()?.resetState();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Make sure that all required managers are registered
|
/// Make sure that all required managers are registered
|
||||||
void _runPreConnectionAssertions() {
|
void _runPreConnectionAssertions() {
|
||||||
@ -1034,7 +1009,7 @@ class XmppConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await _reconnectionPolicy.reset();
|
await _reconnectionPolicy.reset();
|
||||||
_socketClosureTriggersReconnect = true;
|
|
||||||
await _sendEvent(ConnectingEvent());
|
await _sendEvent(ConnectingEvent());
|
||||||
|
|
||||||
final smManager = getStreamManagementManager();
|
final smManager = getStreamManagementManager();
|
||||||
|
@ -93,7 +93,6 @@ class ExponentialBackoffReconnectionPolicy extends ReconnectionPolicy {
|
|||||||
final isReconnecting = await isReconnectionRunning();
|
final isReconnecting = await isReconnectionRunning();
|
||||||
if (shouldReconnect) {
|
if (shouldReconnect) {
|
||||||
if (!isReconnecting) {
|
if (!isReconnecting) {
|
||||||
await setIsReconnecting(true);
|
|
||||||
await performReconnect!();
|
await performReconnect!();
|
||||||
} else {
|
} else {
|
||||||
// Should never happen.
|
// Should never happen.
|
||||||
@ -118,6 +117,7 @@ class ExponentialBackoffReconnectionPolicy extends ReconnectionPolicy {
|
|||||||
Future<void> onFailure() async {
|
Future<void> onFailure() async {
|
||||||
_log.finest('Failure occured. Starting exponential backoff');
|
_log.finest('Failure occured. Starting exponential backoff');
|
||||||
_counter++;
|
_counter++;
|
||||||
|
await setIsReconnecting(true);
|
||||||
|
|
||||||
if (_timer != null) {
|
if (_timer != null) {
|
||||||
_timer!.cancel();
|
_timer!.cancel();
|
||||||
@ -148,23 +148,3 @@ class TestingReconnectionPolicy extends ReconnectionPolicy {
|
|||||||
@override
|
@override
|
||||||
Future<void> reset() async {}
|
Future<void> reset() async {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A reconnection policy for tests that waits a constant number of seconds before
|
|
||||||
/// attempting a reconnection.
|
|
||||||
@visibleForTesting
|
|
||||||
class TestingSleepReconnectionPolicy extends ReconnectionPolicy {
|
|
||||||
TestingSleepReconnectionPolicy(this._sleepAmount) : super();
|
|
||||||
final int _sleepAmount;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onSuccess() async {}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> onFailure() async {
|
|
||||||
await Future<void>.delayed(Duration(seconds: _sleepAmount));
|
|
||||||
await performReconnect!();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> reset() async {}
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: moxxmpp
|
name: moxxmpp
|
||||||
description: A pure-Dart XMPP library
|
description: A pure-Dart XMPP library
|
||||||
version: 0.1.2+2
|
version: 0.1.2+1
|
||||||
homepage: https://codeberg.org/moxxy/moxxmpp
|
homepage: https://codeberg.org/moxxy/moxxmpp
|
||||||
publish_to: https://git.polynom.me/api/packages/Moxxy/pub
|
publish_to: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
|
|
||||||
@ -29,8 +29,5 @@ dependencies:
|
|||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.1.11
|
build_runner: ^2.1.11
|
||||||
moxxmpp_socket_tcp:
|
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
|
||||||
version: ^0.1.2+2
|
|
||||||
test: ^1.16.0
|
test: ^1.16.0
|
||||||
very_good_analysis: ^3.0.1
|
very_good_analysis: ^3.0.1
|
||||||
|
@ -1 +0,0 @@
|
|||||||
pubspec_overrides.yaml
|
|
@ -1,7 +1,3 @@
|
|||||||
## 0.1.2+2
|
|
||||||
|
|
||||||
- **FIX**: Fix reconnections when the connection is awaited.
|
|
||||||
|
|
||||||
## 0.1.2+1
|
## 0.1.2+1
|
||||||
|
|
||||||
- **FIX**: A certificate rejection does not crash the connection.
|
- **FIX**: A certificate rejection does not crash the connection.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: moxxmpp_socket_tcp
|
name: moxxmpp_socket_tcp
|
||||||
description: A socket for moxxmpp using TCP that implements the RFC6120 connection algorithm and XEP-0368
|
description: A socket for moxxmpp using TCP that implements the RFC6120 connection algorithm and XEP-0368
|
||||||
version: 0.1.2+2
|
version: 0.1.2+1
|
||||||
homepage: https://codeberg.org/moxxy/moxxmpp
|
homepage: https://codeberg.org/moxxy/moxxmpp
|
||||||
publish_to: https://git.polynom.me/api/packages/Moxxy/pub
|
publish_to: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ dependencies:
|
|||||||
meta: ^1.6.0
|
meta: ^1.6.0
|
||||||
moxxmpp:
|
moxxmpp:
|
||||||
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
hosted: https://git.polynom.me/api/packages/Moxxy/pub
|
||||||
version: ^0.1.2+2
|
version: ^0.1.2+1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
lints: ^2.0.0
|
lints: ^2.0.0
|
||||||
|
Loading…
Reference in New Issue
Block a user