fix (#195) & opt.

- fix: debug provider color
- fix: can't write script through SFTP (#195)
- opt.: go next refresh only after current refresh task is done
This commit is contained in:
lollipopkit
2023-10-30 12:01:07 +08:00
parent eb0b219505
commit 2b52e8e6ee
6 changed files with 72 additions and 42 deletions

View File

@@ -49,6 +49,7 @@ Future<SSHClient> genClient(
/// [ServerPrivateInfo] of the jump server
ServerPrivateInfo? jumpSpi,
String? jumpPrivateKey,
}) async {
onStatus?.call(GenSSHClientStatus.socket);
SSHSocket? socket;
@@ -76,14 +77,13 @@ Future<SSHClient> genClient(
if (jumpSpi != null) {
final jumpClient = await genClient(
jumpSpi,
privateKey: privateKey,
privateKey: jumpPrivateKey,
timeout: timeout,
);
// Use `0.0.0.0` as localhost to use all interfaces.
return await jumpClient.forwardLocal(
spi.ip,
spi.port,
localHost: '0.0.0.0',
);
}
}();

View File

@@ -5,13 +5,7 @@ const seperator = 'SrvBoxSep';
/// The suffix `\t` is for formatting
const _cmdDivider = '\necho $seperator\n\t';
const _serverBoxDir = r'$HOME/.config/server_box';
/// Issue #159
/// Use script commit count as version of shell script.
/// So different version of app can run at the same time.
const installShellPath = '$_serverBoxDir/mobile_v${BuildData.script}.sh';
const _homeVar = '\$HOME';
enum ShellFunc {
status,
@@ -22,6 +16,31 @@ enum ShellFunc {
suspend,
;
static const _serverBoxDir = '.config/server_box';
static const _scriptFileName = 'mobile_v${BuildData.script}.sh';
/// Issue #159
///
/// Use script commit count as version of shell script.
///
/// So different version of app can run at the same time.
///
/// **Can't** use it in SFTP, because SFTP can't recognize `$HOME`
static String getShellPath(String home) =>
'$home/$_serverBoxDir/$_scriptFileName';
static final _installShellPath = getShellPath(_homeVar);
/// Issue #168
/// Use `sh` for compatibility
static final installShellCmd = """
mkdir -p $_homeVar/$_serverBoxDir
cat << 'EOF' > $_installShellPath
${ShellFunc.allScript}
EOF
chmod +x $_installShellPath
""";
String get flag {
switch (this) {
case ShellFunc.status:
@@ -39,7 +58,7 @@ enum ShellFunc {
}
}
String get exec => 'sh $installShellPath -$flag';
String get exec => 'sh $_installShellPath -$flag';
String get name {
switch (this) {
@@ -241,13 +260,3 @@ const _bsdStatusCmd = [
//'sysctl -a | grep temperature',
'hostname',
];
/// Issue #168
/// Use `sh` for compatibility
final installShellCmd = """
mkdir -p $_serverBoxDir
cat << 'EOF' > $installShellPath
${ShellFunc.allScript}
EOF
chmod +x $installShellPath
""";

View File

@@ -10,9 +10,8 @@ class Server implements TagPickable {
SSHClient? client;
ServerState state;
/// Whether is generating client.
/// Use this to avoid reconnecting if last connect try not finished.
bool isGenerating = false;
/// Whether is connectting, parsing and etc.
bool isBusy = false;
Server(this.spi, this.status, this.client, this.state);

View File

@@ -5,8 +5,8 @@ import 'package:toolbox/data/res/ui.dart';
import '../../data/res/misc.dart';
const _level2Color = {
'[INFO]': Colors.blue,
'[WARNING]': Colors.yellow,
'INFO': Colors.blue,
'WARNING': Colors.yellow,
};
class DebugProvider extends ChangeNotifier {

View File

@@ -246,6 +246,15 @@ class ServerProvider extends ChangeNotifier {
void _setServerState(Server s, ServerState ss) {
s.state = ss;
/// Only set [Sever.isBusy] to false when err occurs or finished.
switch (ss) {
case ServerState.failed || ServerState.finished:
s.isBusy = false;
break;
default:
break;
}
notifyListeners();
}
@@ -262,19 +271,23 @@ class ServerProvider extends ChangeNotifier {
return;
}
/// If busy, it may be because of network reasons that the last request
/// has not been completed, and the request should not be made again at this time.
if (s.isBusy) return;
s.isBusy = true;
if (s.state.shouldConnect || (s.client?.isClosed ?? true)) {
_setServerState(s, ServerState.connecting);
final time1 = DateTime.now();
final jumpSpi =
spi.jumpId == null ? null : Stores.server.box.get(spi.jumpId);
try {
if (s.isGenerating) return;
s.isGenerating = true;
s.client = await genClient(
spi,
timeout: Stores.setting.timeoutD,
jumpSpi:
spi.jumpId == null ? null : Stores.server.box.get(spi.jumpId),
jumpSpi: jumpSpi,
);
} catch (e) {
_limiter.inc(sid);
@@ -284,33 +297,43 @@ class ServerProvider extends ChangeNotifier {
/// In order to keep privacy, print [spi.name] instead of [spi.id]
Loggers.app.warning('Connect to ${spi.name} failed', e);
return;
} finally {
s.isGenerating = false;
}
final time2 = DateTime.now();
final spentTime = time2.difference(time1).inMilliseconds;
if (spi.jumpId == null) {
Loggers.app.info('Connected to ${spi.name} in $spentTime ms.');
} else {
Loggers.app.info(
'Connected to ${spi.name} via ${jumpSpi?.name} in $spentTime ms.');
}
_setServerState(s, ServerState.connected);
// Write script to server
// by ssh
try {
final writeResult = await s.client?.run(installShellCmd).string;
final writeResult =
await s.client?.run(ShellFunc.installShellCmd).string;
if (writeResult == null || writeResult.isNotEmpty) {
throw Exception('$writeResult');
}
} catch (e) {
Loggers.app.warning('Write script to ${spi.name} by shell', e);
// by sftp
final localPath = joinPath(await Paths.doc, 'install.sh');
final file = File(localPath);
try {
Loggers.app.warning('Using SFTP to write script to ${spi.name}');
Loggers.app.info('Using SFTP to write script to ${spi.name}');
file.writeAsString(ShellFunc.allScript);
final completer = Completer();
final homePath = (await s.client?.run('echo \$HOME').string)?.trim();
if (homePath == null || homePath.isEmpty) {
throw Exception('Got home path: $homePath');
}
final remotePath = ShellFunc.getShellPath(homePath);
final reqId = Pros.sftp.add(
SftpReq(spi, installShellPath, localPath, SftpReqType.upload),
SftpReq(spi, remotePath, localPath, SftpReqType.upload),
completer: completer,
);
await completer.future;
@@ -322,7 +345,7 @@ class ServerProvider extends ChangeNotifier {
_limiter.inc(sid);
s.status.failedInfo = e.toString();
_setServerState(s, ServerState.failed);
Loggers.app.warning('Write script to ${spi.name} failed', e);
Loggers.app.warning('Write script to ${spi.name} by sftp', e);
return;
} finally {
if (await file.exists()) await file.delete();
@@ -382,11 +405,8 @@ class ServerProvider extends ChangeNotifier {
return;
}
if (s.state != ServerState.finished) {
/// Call this every time for setting [Server.isBusy] to false
_setServerState(s, ServerState.finished);
} else {
notifyListeners();
}
// reset try times only after prepared successfully
_limiter.reset(sid);
}

View File

@@ -1,3 +1,5 @@
// ignore_for_file: avoid_print
import 'dart:async';
import 'package:flutter/material.dart';
@@ -110,8 +112,8 @@ void _setupLogger() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
Pros.debug.addLog(record);
// ignore: avoid_print
print(record);
if (record.stackTrace != null) print(record.stackTrace);
});
}