Solve ssh connect slow
This commit is contained in:
@@ -17,6 +17,7 @@ import 'package:toolbox/data/model/server/server_private_info.dart';
|
|||||||
import 'package:toolbox/data/model/server/server_status.dart';
|
import 'package:toolbox/data/model/server/server_status.dart';
|
||||||
import 'package:toolbox/data/model/server/snippet.dart';
|
import 'package:toolbox/data/model/server/snippet.dart';
|
||||||
import 'package:toolbox/data/model/server/tcp_status.dart';
|
import 'package:toolbox/data/model/server/tcp_status.dart';
|
||||||
|
import 'package:toolbox/data/store/private_key.dart';
|
||||||
import 'package:toolbox/data/store/server.dart';
|
import 'package:toolbox/data/store/server.dart';
|
||||||
import 'package:toolbox/data/store/setting.dart';
|
import 'package:toolbox/data/store/setting.dart';
|
||||||
import 'package:toolbox/locator.dart';
|
import 'package:toolbox/locator.dart';
|
||||||
@@ -24,8 +25,8 @@ import 'package:toolbox/locator.dart';
|
|||||||
/// Must put this func out of any Class.
|
/// Must put this func out of any Class.
|
||||||
/// Because of this function is called by [compute] in [ServerProvider.genClient].
|
/// Because of this function is called by [compute] in [ServerProvider.genClient].
|
||||||
/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure
|
/// https://stackoverflow.com/questions/51998995/invalid-arguments-illegal-argument-in-isolate-message-object-is-a-closure
|
||||||
List<SSHKeyPair> loadIndentity(Map<String, dynamic> auth) {
|
List<SSHKeyPair> loadIndentity(String key) {
|
||||||
return SSHKeyPair.fromPem(auth['privateKey'], auth['passphrase']);
|
return SSHKeyPair.fromPem(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServerProvider extends BusyProvider {
|
class ServerProvider extends BusyProvider {
|
||||||
@@ -73,14 +74,14 @@ class ServerProvider extends BusyProvider {
|
|||||||
|
|
||||||
Future<SSHClient> genClient(ServerPrivateInfo spi) async {
|
Future<SSHClient> genClient(ServerPrivateInfo spi) async {
|
||||||
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
final socket = await SSHSocket.connect(spi.ip, spi.port);
|
||||||
if (spi.authorization is String) {
|
if (spi.pubKeyId == null) {
|
||||||
return SSHClient(socket,
|
return SSHClient(socket,
|
||||||
username: spi.user,
|
username: spi.user,
|
||||||
onPasswordRequest: () => spi.authorization as String);
|
onPasswordRequest: () => spi.authorization as String);
|
||||||
}
|
}
|
||||||
final auth = spi.authorization as Map<String, dynamic>;
|
final key = locator<PrivateKeyStore>().get(spi.pubKeyId!);
|
||||||
return SSHClient(socket,
|
return SSHClient(socket,
|
||||||
username: spi.user, identities: await compute(loadIndentity, auth));
|
username: spi.user, identities: await compute(loadIndentity, key.privateKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> refreshData({int? idx}) async {
|
Future<void> refreshData({int? idx}) async {
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ToolBox";
|
static const String name = "ToolBox";
|
||||||
static const int build = 79;
|
static const int build = 79;
|
||||||
static const String engine = "Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 77d935af4d (4 weeks ago) • 2021-12-16 08:37:33 -0800\nEngine • revision 890a5fca2e\nTools • Dart 2.15.1\n";
|
static const String engine =
|
||||||
|
"Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 77d935af4d (4 weeks ago) • 2021-12-16 08:37:33 -0800\nEngine • revision 890a5fca2e\nTools • Dart 2.15.1\n";
|
||||||
static const String buildAt = "2022-01-10 16:04:12.547744";
|
static const String buildAt = "2022-01-10 16:04:12.547744";
|
||||||
static const int modifications = 0;
|
static const int modifications = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ class PrivateKeyStore extends PersistentStore {
|
|||||||
json.decode(box.get('key', defaultValue: '[]')!));
|
json.decode(box.get('key', defaultValue: '[]')!));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrivateKeyInfo get(String id) {
|
||||||
|
final ss = fetch();
|
||||||
|
return ss.firstWhere((e) => e.id == id);
|
||||||
|
}
|
||||||
|
|
||||||
void delete(PrivateKeyInfo s) {
|
void delete(PrivateKeyInfo s) {
|
||||||
final ss = fetch();
|
final ss = fetch();
|
||||||
ss.removeAt(index(s));
|
ss.removeAt(index(s));
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:after_layout/after_layout.dart';
|
import 'package:after_layout/after_layout.dart';
|
||||||
|
import 'package:dartssh2/dartssh2.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:toolbox/core/utils.dart';
|
import 'package:toolbox/core/utils.dart';
|
||||||
import 'package:toolbox/data/model/server/private_key_info.dart';
|
import 'package:toolbox/data/model/server/private_key_info.dart';
|
||||||
@@ -22,11 +24,13 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
final pwdController = TextEditingController();
|
final pwdController = TextEditingController();
|
||||||
|
|
||||||
late PrivateKeyProvider _provider;
|
late PrivateKeyProvider _provider;
|
||||||
|
late Widget loading;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_provider = locator<PrivateKeyProvider>();
|
_provider = locator<PrivateKeyProvider>();
|
||||||
|
loading = const SizedBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -66,11 +70,13 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: buildDecoration('Password', icon: Icons.password),
|
decoration: buildDecoration('Password', icon: Icons.password),
|
||||||
),
|
),
|
||||||
|
SizedBox(height: MediaQuery.of(context).size.height * 0.1),
|
||||||
|
loading
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
child: const Icon(Icons.send),
|
child: const Icon(Icons.save),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
final name = nameController.text;
|
final name = nameController.text;
|
||||||
final key = keyController.text;
|
final key = keyController.text;
|
||||||
final pwd = pwdController.text;
|
final pwd = pwdController.text;
|
||||||
@@ -79,7 +85,28 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
context, const Text('Three fields must not be empty.'));
|
context, const Text('Three fields must not be empty.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
FocusScope.of(context).unfocus();
|
||||||
|
setState(() {
|
||||||
|
loading = const SizedBox(
|
||||||
|
height: 50,
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
final info = PrivateKeyInfo(name, key, pwd);
|
final info = PrivateKeyInfo(name, key, pwd);
|
||||||
|
bool haveErr = false;
|
||||||
|
try {
|
||||||
|
info.privateKey = await compute(decyptPem, [key, pwd]);
|
||||||
|
} catch (e) {
|
||||||
|
showSnackBar(context, Text(e.toString()));
|
||||||
|
haveErr = true;
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
loading = const SizedBox();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (haveErr) return;
|
||||||
if (widget.info != null) {
|
if (widget.info != null) {
|
||||||
_provider.updateInfo(widget.info!, info);
|
_provider.updateInfo(widget.info!, info);
|
||||||
} else {
|
} else {
|
||||||
@@ -100,3 +127,11 @@ class _PrivateKeyEditPageState extends State<PrivateKeyEditPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [args] : [key, pwd]
|
||||||
|
String decyptPem(List<String> args) {
|
||||||
|
/// skip when the key is not encrypted, or will throw exception
|
||||||
|
if (!SSHKeyPair.isEncryptedPem(args[0])) return args[0];
|
||||||
|
final sshKey = SSHKeyPair.fromPem(args[0], args[1]);
|
||||||
|
return sshKey.first.toPem();
|
||||||
|
}
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ packages:
|
|||||||
name: dartssh2
|
name: dartssh2
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-pre"
|
version: "2.2.0"
|
||||||
dio:
|
dio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/Countly/countly-sdk-flutter-bridge.git
|
url: https://github.com/Countly/countly-sdk-flutter-bridge.git
|
||||||
ref: master
|
ref: master
|
||||||
dartssh2: ^2.1.0-pre
|
dartssh2: ^2.2.0
|
||||||
logging: ^1.0.2
|
logging: ^1.0.2
|
||||||
flutter_material_color_picker: ^1.1.0+2
|
flutter_material_color_picker: ^1.1.0+2
|
||||||
circle_chart:
|
circle_chart:
|
||||||
|
|||||||
Reference in New Issue
Block a user