Compare commits

..

4 Commits

6 changed files with 118 additions and 107 deletions

View File

@ -5,7 +5,7 @@ import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
class ExampleTcpSocketWrapper extends TCPSocketWrapper {
ExampleTcpSocketWrapper() : super(false);
ExampleTcpSocketWrapper() : super();
@override
Future<List<MoxSrvRecord>> srvQuery(String domain, bool dnssec) async {
@ -64,7 +64,7 @@ class _MyHomePageState extends State<MyHomePage> {
// The below causes the app to crash.
//ExampleTcpSocketWrapper(),
// In a production app, the below should be false.
TCPSocketWrapper(true),
TCPSocketWrapper(),
);
TextEditingController jidController = TextEditingController();
TextEditingController passwordController = TextEditingController();

View File

@ -397,6 +397,9 @@ class XmppConnection {
return;
}
// Close the socket
_socket.close();
if (!error.isRecoverable()) {
// We cannot recover this error
_log.severe(

View File

@ -5,7 +5,7 @@ import 'package:test/test.dart';
Future<void> _runTest(String domain) async {
var gotTLSException = false;
final socket = TCPSocketWrapper(false);
final socket = TCPSocketWrapper();
final log = Logger('TestLogger');
socket.getEventStream().listen((event) {
if (event is XmppSocketTLSFailedEvent) {
@ -15,18 +15,17 @@ Future<void> _runTest(String domain) async {
});
final connection = XmppConnection(
ExponentialBackoffReconnectionPolicy(),
TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(),
socket,
);
connection.registerFeatureNegotiators([
StartTlsNegotiator(),
]);
connection.registerManagers([
DiscoManager(),
RosterManager(),
PingManager(),
)..registerFeatureNegotiators([
StartTlsNegotiator(),
]);
await connection.registerManagers([
DiscoManager([]),
RosterManager(TestingRosterStateManager('', [])),
MessageManager(),
PresenceManager('http://moxxmpp.example'),
PresenceManager(),
]);
connection.setConnectionSettings(
@ -34,18 +33,22 @@ Future<void> _runTest(String domain) async {
jid: JID.fromString('testuser@$domain'),
password: 'abc123',
useDirectTLS: true,
allowPlainAuth: true,
),
);
final result = await connection.connectAwaitable();
expect(result.success, false);
final result = await connection.connect(
shouldReconnect: false,
waitUntilLogin: true,
enableReconnectOnSuccess: false,
);
expect(result.isType<XmppError>(), false);
expect(gotTLSException, true);
}
void main() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
// ignore: avoid_print
print('${record.level.name}: ${record.time}: ${record.message}');
});

View File

@ -6,93 +6,106 @@ import 'package:test/test.dart';
void main() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
// ignore: avoid_print
print('${record.level.name}: ${record.time}: ${record.message}');
});
final log = Logger('FailureReconnectionTest');
test('Failing an awaited connection with TestingSleepReconnectionPolicy', () 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++;
test(
'Failing an awaited connection with TestingSleepReconnectionPolicy',
() async {
var errors = 0;
final connection = XmppConnection(
TestingSleepReconnectionPolicy(10),
AlwaysConnectedConnectivityManager(),
TCPSocketWrapper(),
)..registerFeatureNegotiators([
StartTlsNegotiator(),
]);
await connection.registerManagers([
DiscoManager([]),
RosterManager(TestingRosterStateManager('', [])),
MessageManager(),
PresenceManager(),
]);
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,
),
);
connection.setConnectionSettings(
ConnectionSettings(
jid: JID.fromString('testuser@no-sasl.badxmpp.eu'),
password: 'abc123',
useDirectTLS: true,
),
);
final result = await connection.connectAwaitable();
log.info('Connection failed as expected');
expect(result.success, false);
expect(errors, 1);
final result = await connection.connect(
shouldReconnect: false,
waitUntilLogin: true,
enableReconnectOnSuccess: false,
);
log.info('Connection failed as expected');
expect(result.isType<XmppError>(), 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));
log.info('Waiting 20 seconds for unexpected reconnections');
await Future<void>.delayed(const Duration(seconds: 20));
expect(errors, 1);
},
timeout: const Timeout.factor(2),
);
test('Failing an awaited connection with ExponentialBackoffReconnectionPolicy', () async {
var errors = 0;
final connection = XmppConnection(
ExponentialBackoffReconnectionPolicy(1),
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++;
test(
'Failing an awaited connection with ExponentialBackoffReconnectionPolicy',
() async {
var errors = 0;
final connection = XmppConnection(
TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(),
TCPSocketWrapper(),
)..registerFeatureNegotiators([
StartTlsNegotiator(),
]);
await connection.registerManagers([
DiscoManager([]),
RosterManager(TestingRosterStateManager('', [])),
MessageManager(),
PresenceManager(),
]);
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,
),
);
connection.setConnectionSettings(
ConnectionSettings(
jid: JID.fromString('testuser@no-sasl.badxmpp.eu'),
password: 'abc123',
useDirectTLS: true,
),
);
final result = await connection.connectAwaitable();
log.info('Connection failed as expected');
expect(result.success, false);
expect(errors, 1);
final result = await connection.connect(
shouldReconnect: false,
waitUntilLogin: true,
enableReconnectOnSuccess: false,
);
log.info('Connection failed as expected');
expect(result.isType<XmppError>(), 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));
log.info('Waiting 20 seconds for unexpected reconnections');
await Future<void>.delayed(const Duration(seconds: 20));
expect(errors, 1);
},
timeout: const Timeout.factor(2),
);
}

View File

@ -10,8 +10,6 @@ import 'package:moxxmpp_socket_tcp/src/rfc_2782.dart';
/// TCP socket implementation for XmppConnection
class TCPSocketWrapper extends BaseSocketWrapper {
TCPSocketWrapper(this._logData);
/// The underlying Socket/SecureSocket instance.
Socket? _socket;
@ -31,9 +29,6 @@ class TCPSocketWrapper extends BaseSocketWrapper {
/// Logger
final Logger _log = Logger('TCPSocketWrapper');
/// Flag to indicate if incoming and outgoing data should get logged.
final bool _logData;
/// Indiacted whether the connection is secure.
bool _secure = false;
@ -217,9 +212,7 @@ class TCPSocketWrapper extends BaseSocketWrapper {
_socketSubscription = _socket!.listen(
(List<int> event) {
final data = utf8.decode(event);
if (_logData) {
_log.finest('<== $data');
}
_log.finest('<== $data');
_dataStream.add(data);
},
onError: (Object error) {
@ -296,18 +289,16 @@ class TCPSocketWrapper extends BaseSocketWrapper {
_eventStream.stream.asBroadcastStream();
@override
void write(Object? data, {String? redact}) {
void write(String data, {String? redact}) {
if (_socket == null) {
_log.severe('Failed to write to socket as _socket is null');
return;
}
if (data != null && data is String && _logData) {
if (redact != null) {
_log.finest('**> $redact');
} else {
_log.finest('==> $data');
}
if (redact != null) {
_log.finest('**> $redact');
} else {
_log.finest('==> $data');
}
try {