Line data Source code
1 : import 'dart:async';
2 : import 'dart:io';
3 :
4 : import 'package:at_client/at_client.dart';
5 : import 'package:at_client/src/client/secondary.dart';
6 : import 'package:at_commons/at_builders.dart';
7 : import 'package:at_lookup/at_lookup.dart';
8 : import 'package:at_utils/at_utils.dart';
9 : import 'package:internet_connection_checker/internet_connection_checker.dart';
10 :
11 : /// Contains methods used to execute verbs on remote secondary server of the atSign.
12 : class RemoteSecondary implements Secondary {
13 : var logger = AtSignLogger('RemoteSecondary');
14 :
15 : late String _atSign;
16 :
17 : late AtClientPreference _preference;
18 :
19 : late AtLookupImpl atLookUp;
20 :
21 2 : RemoteSecondary(String atSign, AtClientPreference preference,
22 : {String? privateKey}) {
23 4 : _atSign = AtUtils.formatAtSign(atSign)!;
24 2 : _preference = preference;
25 2 : privateKey ??= preference.privateKey;
26 8 : atLookUp = AtLookupImpl(atSign, preference.rootDomain, preference.rootPort,
27 2 : privateKey: privateKey, cramSecret: preference.cramSecret);
28 : }
29 :
30 : /// Executes the command returned by [VerbBuilder] build command on a remote secondary server.
31 : /// Optionally [privateKey] is passed for verb builders which require authentication.
32 : @override
33 0 : Future<String> executeVerb(VerbBuilder builder, {sync = false}) async {
34 : String verbResult;
35 0 : verbResult = await atLookUp.executeVerb(builder);
36 : return verbResult;
37 : }
38 :
39 0 : Future<String> executeAndParse(VerbBuilder builder, {sync = false}) async {
40 0 : var verbResult = await executeVerb(builder);
41 0 : verbResult = verbResult.replaceFirst('data:', '');
42 : return verbResult;
43 : }
44 :
45 0 : Future<String?> executeCommand(String atCommand, {bool auth = false}) async {
46 : String? verbResult;
47 0 : verbResult = await atLookUp.executeCommand(atCommand, auth: auth);
48 : return verbResult;
49 : }
50 :
51 0 : void addStreamData(List<int> data) {
52 0 : atLookUp.connection!.getSocket().add(data);
53 : }
54 :
55 : /// Generates digest using from verb response and [privateKey] and performs a PKAM authentication to
56 : /// secondary server. This method is executed for all verbs that requires authentication.
57 0 : Future<bool> authenticate(var privateKey) async {
58 0 : var authResult = await atLookUp.authenticate(privateKey);
59 : return authResult;
60 : }
61 :
62 : /// Generates digest using from verb response and [secret] and performs a CRAM authentication to
63 : /// secondary server
64 0 : Future<bool> authenticateCram(var secret) async {
65 0 : var authResult = await atLookUp.authenticate_cram(secret);
66 : return authResult;
67 : }
68 :
69 : /// Executes sync verb on the remote server. Return commit entries greater than [lastSyncedId].
70 0 : Future<String?> sync(int? lastSyncedId, {String? regex}) async {
71 0 : var syncVerbBuilder = SyncVerbBuilder()
72 0 : ..commitId = lastSyncedId
73 0 : ..regex = regex
74 0 : ..limit = _preference.syncPageLimit;
75 :
76 0 : var atCommand = syncVerbBuilder.buildCommand();
77 0 : return await atLookUp.executeCommand(atCommand, auth: true);
78 : }
79 :
80 : ///Executes monitor verb on remote secondary. Result of the monitor verb is processed using [monitorResponseCallback].
81 0 : Future<OutboundConnection> monitor(
82 : String command, Function? notificationCallBack, String privateKey) {
83 0 : return MonitorClient(privateKey).executeMonitorVerb(
84 0 : command, _atSign, _preference.rootDomain, _preference.rootPort,
85 0 : (value) {
86 0 : notificationCallBack!(value);
87 0 : }, restartCallBack: _restartCallBack);
88 : }
89 :
90 0 : Future<bool> isAvailable() async {
91 : try {
92 0 : var secondaryUrl = await AtLookupImpl.findSecondary(
93 0 : _atSign, _preference.rootDomain, _preference.rootPort);
94 0 : var secondaryInfo = AtClientUtil.getSecondaryInfo(secondaryUrl);
95 0 : var host = secondaryInfo[0];
96 0 : var port = secondaryInfo[1];
97 0 : var internetAddress = await InternetAddress.lookup(host);
98 : //TODO getting first ip for now. explore best solution
99 : var addressCheckOptions =
100 0 : AddressCheckOptions(internetAddress[0], port: int.parse(port));
101 0 : return (await InternetConnectionChecker()
102 0 : .isHostReachable(addressCheckOptions))
103 0 : .isSuccess;
104 0 : } on Exception catch (e) {
105 0 : logger.severe('Secondary server unavailable ${e.toString}');
106 0 : } on Error catch (e) {
107 0 : logger.severe('Secondary server unavailable ${e.toString}');
108 : }
109 : return false;
110 : }
111 :
112 0 : Future<void> _restartCallBack(
113 : String command, Function notificationCallBack, String privateKey) async {
114 0 : logger.info('auto restarting monitor');
115 0 : await monitor(command, notificationCallBack, privateKey);
116 : }
117 : }
|