Merge pull request 'Merge connect
and connectAwaitable
' (#32) from refactor/connect into master
Reviewed-on: https://codeberg.org/moxxy/moxxmpp/pulls/32
This commit is contained in:
commit
324ef9ca29
@ -117,19 +117,19 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
allowPlainAuth: true,
|
allowPlainAuth: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final result = await connection.connectAwaitable();
|
final result = await connection.connect(waitUntilLogin: true);
|
||||||
setState(() {
|
setState(() {
|
||||||
connected = result.success;
|
connected = result.isType<bool>() && result.get<bool>();
|
||||||
loading = false;
|
loading = false;
|
||||||
});
|
});
|
||||||
if (result.error != null) {
|
if (result.isType<XmppConnectionError>()) {
|
||||||
logger.severe(result.error);
|
logger.severe(result.get<XmppConnectionError>());
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => AlertDialog(
|
builder: (_) => AlertDialog(
|
||||||
title: const Text('Error'),
|
title: const Text('Error'),
|
||||||
content: Text(result.error.toString()),
|
content: Text(result.get<XmppConnectionError>().toString()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
useGoogleAPIs = false;
|
useGoogleAPIs = false;
|
||||||
useGoogleTVAddOns = false;
|
useGoogleTVAddOns = false;
|
||||||
};
|
};
|
||||||
pinnedJDK = pkgs.jdk;
|
pinnedJDK = pkgs.jdk17;
|
||||||
|
|
||||||
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||||
pyyaml
|
pyyaml
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
## 0.3.0
|
||||||
|
|
||||||
|
- **BREAKING**: Removed `connectAwaitable` and merged it with `connect`.
|
||||||
|
|
||||||
## 0.1.6+1
|
## 0.1.6+1
|
||||||
|
|
||||||
- **FIX**: Fix LMC not working.
|
- **FIX**: Fix LMC not working.
|
||||||
|
@ -4,6 +4,7 @@ import 'package:meta/meta.dart';
|
|||||||
import 'package:moxlib/moxlib.dart';
|
import 'package:moxlib/moxlib.dart';
|
||||||
import 'package:moxxmpp/src/awaiter.dart';
|
import 'package:moxxmpp/src/awaiter.dart';
|
||||||
import 'package:moxxmpp/src/buffer.dart';
|
import 'package:moxxmpp/src/buffer.dart';
|
||||||
|
import 'package:moxxmpp/src/connection_errors.dart';
|
||||||
import 'package:moxxmpp/src/connectivity.dart';
|
import 'package:moxxmpp/src/connectivity.dart';
|
||||||
import 'package:moxxmpp/src/errors.dart';
|
import 'package:moxxmpp/src/errors.dart';
|
||||||
import 'package:moxxmpp/src/events.dart';
|
import 'package:moxxmpp/src/events.dart';
|
||||||
@ -24,6 +25,7 @@ import 'package:moxxmpp/src/settings.dart';
|
|||||||
import 'package:moxxmpp/src/socket.dart';
|
import 'package:moxxmpp/src/socket.dart';
|
||||||
import 'package:moxxmpp/src/stanza.dart';
|
import 'package:moxxmpp/src/stanza.dart';
|
||||||
import 'package:moxxmpp/src/stringxml.dart';
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
|
import 'package:moxxmpp/src/types/result.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
|
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0198/negotiator.dart';
|
import 'package:moxxmpp/src/xeps/xep_0198/negotiator.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0198/xep_0198.dart';
|
import 'package:moxxmpp/src/xeps/xep_0198/xep_0198.dart';
|
||||||
@ -75,21 +77,6 @@ class StreamHeaderNonza extends XMLNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The result of an awaited connection.
|
|
||||||
class XmppConnectionResult {
|
|
||||||
const XmppConnectionResult(
|
|
||||||
this.success, {
|
|
||||||
this.error,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// True if the connection was successful. False if it failed for any reason.
|
|
||||||
final bool success;
|
|
||||||
|
|
||||||
// If a connection attempt fails, i.e. success is false, then this indicates the
|
|
||||||
// reason the connection failed.
|
|
||||||
final XmppError? error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This class is a connection to the server.
|
/// This class is a connection to the server.
|
||||||
class XmppConnection {
|
class XmppConnection {
|
||||||
XmppConnection(
|
XmppConnection(
|
||||||
@ -180,7 +167,7 @@ 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<Result<bool, XmppConnectionError>>? _connectionCompleter;
|
||||||
|
|
||||||
/// Negotiators
|
/// Negotiators
|
||||||
final Map<String, XmppFeatureNegotiatorBase> _featureNegotiators = {};
|
final Map<String, XmppFeatureNegotiatorBase> _featureNegotiators = {};
|
||||||
@ -198,6 +185,9 @@ class XmppConnection {
|
|||||||
bool _isConnectionRunning = false;
|
bool _isConnectionRunning = false;
|
||||||
final Lock _connectionRunningLock = Lock();
|
final Lock _connectionRunningLock = Lock();
|
||||||
|
|
||||||
|
/// Flag indicating whether reconnection should be enabled after a successful connection.
|
||||||
|
bool _enableReconnectOnSuccess = false;
|
||||||
|
|
||||||
/// Enters the critical section for accessing [XmppConnection._isConnectionRunning]
|
/// Enters the critical section for accessing [XmppConnection._isConnectionRunning]
|
||||||
/// and does the following:
|
/// and does the following:
|
||||||
/// - if _isConnectionRunning is false, set it to true and return false.
|
/// - if _isConnectionRunning is false, set it to true and return false.
|
||||||
@ -404,9 +394,10 @@ class XmppConnection {
|
|||||||
state: XmppConnectionState.error,
|
state: XmppConnectionState.error,
|
||||||
);
|
);
|
||||||
_connectionCompleter?.complete(
|
_connectionCompleter?.complete(
|
||||||
XmppConnectionResult(
|
Result(
|
||||||
false,
|
StreamFailureError(
|
||||||
error: error,
|
error,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
_connectionCompleter = null;
|
_connectionCompleter = null;
|
||||||
@ -427,7 +418,14 @@ class XmppConnection {
|
|||||||
|
|
||||||
// The error is recoverable
|
// The error is recoverable
|
||||||
await _setConnectionState(XmppConnectionState.notConnected);
|
await _setConnectionState(XmppConnectionState.notConnected);
|
||||||
await _reconnectionPolicy.onFailure();
|
|
||||||
|
if (await _reconnectionPolicy.getShouldReconnect()) {
|
||||||
|
await _reconnectionPolicy.onFailure();
|
||||||
|
} else {
|
||||||
|
_log.info(
|
||||||
|
'Not passing connection failure to reconnection policy as it indicates that we should not reconnect',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called whenever the socket creates an event
|
/// Called whenever the socket creates an event
|
||||||
@ -859,8 +857,13 @@ class XmppConnection {
|
|||||||
await _resetIsConnectionRunning();
|
await _resetIsConnectionRunning();
|
||||||
await _setConnectionState(XmppConnectionState.connected);
|
await _setConnectionState(XmppConnectionState.connected);
|
||||||
|
|
||||||
|
// Enable reconnections
|
||||||
|
if (_enableReconnectOnSuccess) {
|
||||||
|
await _reconnectionPolicy.setShouldReconnect(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve the connection completion future
|
// Resolve the connection completion future
|
||||||
_connectionCompleter?.complete(const XmppConnectionResult(true));
|
_connectionCompleter?.complete(const Result(true));
|
||||||
_connectionCompleter = null;
|
_connectionCompleter = null;
|
||||||
|
|
||||||
// Tell consumers of the event stream that we're done with stream feature
|
// Tell consumers of the event stream that we're done with stream feature
|
||||||
@ -1112,47 +1115,30 @@ class XmppConnection {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like [connect] but the Future resolves when the resource binding is either done or
|
Future<Result<bool, XmppConnectionError>> _connectImpl({
|
||||||
/// SASL has failed.
|
|
||||||
Future<XmppConnectionResult> connectAwaitable({
|
|
||||||
String? lastResource,
|
|
||||||
bool waitForConnection = false,
|
|
||||||
}) async {
|
|
||||||
_runPreConnectionAssertions();
|
|
||||||
await _resetIsConnectionRunning();
|
|
||||||
_connectionCompleter = Completer();
|
|
||||||
_log.finest('Calling connect() from connectAwaitable');
|
|
||||||
await connect(
|
|
||||||
lastResource: lastResource,
|
|
||||||
waitForConnection: waitForConnection,
|
|
||||||
shouldReconnect: false,
|
|
||||||
);
|
|
||||||
return _connectionCompleter!.future;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Start the connection process using the provided connection settings.
|
|
||||||
Future<void> connect({
|
|
||||||
String? lastResource,
|
String? lastResource,
|
||||||
bool waitForConnection = false,
|
bool waitForConnection = false,
|
||||||
bool shouldReconnect = true,
|
bool shouldReconnect = true,
|
||||||
|
bool waitUntilLogin = false,
|
||||||
|
bool enableReconnectOnSuccess = true,
|
||||||
}) async {
|
}) async {
|
||||||
if (_connectionState != XmppConnectionState.notConnected &&
|
|
||||||
_connectionState != XmppConnectionState.error) {
|
|
||||||
_log.fine(
|
|
||||||
'Cancelling this connection attempt as one appears to be already running.',
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_runPreConnectionAssertions();
|
_runPreConnectionAssertions();
|
||||||
await _resetIsConnectionRunning();
|
await _resetIsConnectionRunning();
|
||||||
|
|
||||||
|
if (waitUntilLogin) {
|
||||||
|
_log.finest('Setting up completer for awaiting completed login');
|
||||||
|
_connectionCompleter = Completer();
|
||||||
|
}
|
||||||
|
|
||||||
if (lastResource != null) {
|
if (lastResource != null) {
|
||||||
setResource(lastResource);
|
setResource(lastResource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_enableReconnectOnSuccess = enableReconnectOnSuccess;
|
||||||
if (shouldReconnect) {
|
if (shouldReconnect) {
|
||||||
await _reconnectionPolicy.setShouldReconnect(true);
|
await _reconnectionPolicy.setShouldReconnect(true);
|
||||||
|
} else {
|
||||||
|
await _reconnectionPolicy.setShouldReconnect(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _reconnectionPolicy.reset();
|
await _reconnectionPolicy.reset();
|
||||||
@ -1182,6 +1168,8 @@ class XmppConnection {
|
|||||||
);
|
);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
await handleError(NoConnectionError());
|
await handleError(NoConnectionError());
|
||||||
|
|
||||||
|
return Result(NoConnectionPossibleError());
|
||||||
} else {
|
} else {
|
||||||
await _reconnectionPolicy.onSuccess();
|
await _reconnectionPolicy.onSuccess();
|
||||||
_log.fine('Preparing the internal state for a connection attempt');
|
_log.fine('Preparing the internal state for a connection attempt');
|
||||||
@ -1190,6 +1178,67 @@ class XmppConnection {
|
|||||||
_updateRoutingState(RoutingState.negotiating);
|
_updateRoutingState(RoutingState.negotiating);
|
||||||
_isAuthenticated = false;
|
_isAuthenticated = false;
|
||||||
_sendStreamHeader();
|
_sendStreamHeader();
|
||||||
|
|
||||||
|
if (waitUntilLogin) {
|
||||||
|
return _connectionCompleter!.future;
|
||||||
|
} else {
|
||||||
|
return const Result(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start the connection process using the provided connection settings.
|
||||||
|
///
|
||||||
|
/// If [lastResource] is set, then its value is used as the connection's resource.
|
||||||
|
/// Useful for stream resumption.
|
||||||
|
///
|
||||||
|
/// [shouldReconnect] indicates whether the reconnection attempts should be
|
||||||
|
/// automatically performed after a fatal failure of any kind occurs.
|
||||||
|
///
|
||||||
|
/// [waitForConnection] indicates whether the connection should wait for the "go"
|
||||||
|
/// signal from a registered connectivity manager.
|
||||||
|
///
|
||||||
|
/// If [waitUntilLogin] is set to true, the future will resolve when either
|
||||||
|
/// the connection has been successfully established (authentication included) or
|
||||||
|
/// a failure occured. If set to false, then the future will immediately resolve
|
||||||
|
/// to true.
|
||||||
|
///
|
||||||
|
/// [enableReconnectOnSuccess] indicates that automatic reconnection is to be
|
||||||
|
/// enabled once the connection has been successfully established.
|
||||||
|
Future<Result<bool, XmppConnectionError>> connect({
|
||||||
|
String? lastResource,
|
||||||
|
bool? shouldReconnect,
|
||||||
|
bool waitForConnection = false,
|
||||||
|
bool waitUntilLogin = false,
|
||||||
|
bool enableReconnectOnSuccess = true,
|
||||||
|
}) async {
|
||||||
|
if (_connectionState != XmppConnectionState.notConnected &&
|
||||||
|
_connectionState != XmppConnectionState.error) {
|
||||||
|
_log.fine(
|
||||||
|
'Cancelling this connection attempt as one appears to be already running.',
|
||||||
|
);
|
||||||
|
return Future.value(
|
||||||
|
Result(
|
||||||
|
ConnectionAlreadyRunningError(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final result = _connectImpl(
|
||||||
|
lastResource: lastResource,
|
||||||
|
shouldReconnect: shouldReconnect ?? !waitUntilLogin,
|
||||||
|
waitForConnection: waitForConnection,
|
||||||
|
waitUntilLogin: waitUntilLogin,
|
||||||
|
enableReconnectOnSuccess: enableReconnectOnSuccess,
|
||||||
|
);
|
||||||
|
if (waitUntilLogin) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return Future.value(
|
||||||
|
const Result(
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
packages/moxxmpp/lib/src/connection_errors.dart
Normal file
28
packages/moxxmpp/lib/src/connection_errors.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:moxxmpp/src/errors.dart';
|
||||||
|
import 'package:moxxmpp/src/negotiators/negotiator.dart';
|
||||||
|
|
||||||
|
/// The reason a call to `XmppConnection.connect` failed.
|
||||||
|
abstract class XmppConnectionError {}
|
||||||
|
|
||||||
|
/// Returned by `XmppConnection.connect` when a connection is already active.
|
||||||
|
class ConnectionAlreadyRunningError extends XmppConnectionError {}
|
||||||
|
|
||||||
|
/// Returned by `XmppConnection.connect` when a negotiator returned an unrecoverable
|
||||||
|
/// error. Only returned when waitUntilLogin is true.
|
||||||
|
class NegotiatorReturnedError extends XmppConnectionError {
|
||||||
|
NegotiatorReturnedError(this.error);
|
||||||
|
|
||||||
|
/// The error returned by the negotiator.
|
||||||
|
final NegotiatorError error;
|
||||||
|
}
|
||||||
|
|
||||||
|
class StreamFailureError extends XmppConnectionError {
|
||||||
|
StreamFailureError(this.error);
|
||||||
|
|
||||||
|
/// The error that causes a connection failure.
|
||||||
|
final XmppError error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returned by `XmppConnection.connect` when no connection could
|
||||||
|
/// be established.
|
||||||
|
class NoConnectionPossibleError extends XmppConnectionError {}
|
@ -1,6 +1,6 @@
|
|||||||
name: moxxmpp
|
name: moxxmpp
|
||||||
description: A pure-Dart XMPP library
|
description: A pure-Dart XMPP library
|
||||||
version: 0.2.0
|
version: 0.3.0
|
||||||
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
|
||||||
|
|
||||||
|
@ -160,13 +160,13 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final result = await manager.preprocessPublishOptions(
|
// final result = await manager.preprocessPublishOptions(
|
||||||
'pubsub.server.example.org',
|
// 'pubsub.server.example.org',
|
||||||
'example:node',
|
// 'example:node',
|
||||||
PubSubPublishOptions(
|
// PubSubPublishOptions(
|
||||||
maxItems: 'max',
|
// maxItems: 'max',
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user