authenticate method
Authenticates the current communicator. The Future will resolve with
a valid WebSocketCommunicator
if the authentication is successful and
null
otherwise.
Implementation
@override
Future<WebSocketCommunicator?> authenticate({
required Stream<DeviceCommand> commandStream,
required WebSocket socket,
}) async {
final state = AuthenticationState(
commandStream: commandStream,
socket: socket,
);
Completer? completer = Completer<void>();
final future = completer.future;
final timer = Timer(const Duration(minutes: 2), () async {
try {
logger.info(
'[CONNECTION]: connection timed out.',
);
completer?.completeError('[CONNECTION]: connection timed out.');
completer = null;
} catch (e) {
// no-op
}
});
final sub = commandStream.listen((cmd) async {
if (_handlers.containsKey(cmd.type)) {
final handler = _handlers[cmd.type];
await handler!.handle(
command: cmd,
state: state,
);
if (state.success != null) {
completer?.complete();
completer = null;
}
} else {
logger.info(
'[CLOSE]: unknown command type: [${cmd.type}], ignoring...',
);
completer?.complete(null);
completer = null;
}
}, onError: (Object e, StackTrace stack) {
logger.severe('[SOCKET]: error listening to socket', e, stack);
completer?.completeError('[SOCKET]: error listening to socket');
completer = null;
});
try {
await future;
} catch (e, stack) {
logger.severe('Error in authenticator', e, stack);
}
timer.cancel();
await sub.cancel();
if (state.success == true) {
state.communicator!.attachSocket(socket);
}
return state.success == true ? state.communicator : null;
}