From 2b52e8e6eea1b4b53ded644aee449cdc2d686c41 Mon Sep 17 00:00:00 2001 From: lollipopkit Date: Mon, 30 Oct 2023 12:01:07 +0800 Subject: [PATCH] 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 --- lib/core/utils/server.dart | 4 +-- lib/data/model/app/shell_func.dart | 45 +++++++++++++++----------- lib/data/model/server/server.dart | 5 ++- lib/data/provider/debug.dart | 4 +-- lib/data/provider/server.dart | 52 +++++++++++++++++++++--------- lib/main.dart | 4 ++- 6 files changed, 72 insertions(+), 42 deletions(-) diff --git a/lib/core/utils/server.dart b/lib/core/utils/server.dart index 41aa8ff9..4ad1d093 100644 --- a/lib/core/utils/server.dart +++ b/lib/core/utils/server.dart @@ -49,6 +49,7 @@ Future genClient( /// [ServerPrivateInfo] of the jump server ServerPrivateInfo? jumpSpi, + String? jumpPrivateKey, }) async { onStatus?.call(GenSSHClientStatus.socket); SSHSocket? socket; @@ -76,14 +77,13 @@ Future 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', ); } }(); diff --git a/lib/data/model/app/shell_func.dart b/lib/data/model/app/shell_func.dart index 6b654668..9a05b44c 100644 --- a/lib/data/model/app/shell_func.dart +++ b/lib/data/model/app/shell_func.dart @@ -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 -"""; diff --git a/lib/data/model/server/server.dart b/lib/data/model/server/server.dart index 6b9d6b85..e792b9bf 100644 --- a/lib/data/model/server/server.dart +++ b/lib/data/model/server/server.dart @@ -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); diff --git a/lib/data/provider/debug.dart b/lib/data/provider/debug.dart index bf6ca5c7..c5fdd8b3 100644 --- a/lib/data/provider/debug.dart +++ b/lib/data/provider/debug.dart @@ -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 { diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 614646e3..bb8fac93 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -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; - Loggers.app.info('Connected to ${spi.name} in $spentTime ms.'); + 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) { - _setServerState(s, ServerState.finished); - } else { - notifyListeners(); - } + /// Call this every time for setting [Server.isBusy] to false + _setServerState(s, ServerState.finished); // reset try times only after prepared successfully _limiter.reset(sid); } diff --git a/lib/main.dart b/lib/main.dart index 57949b48..c12a7704 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -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); }); }