mirror of
https://github.com/Auties00/Reboot-Launcher.git
synced 2026-01-13 11:12:23 +01:00
10.0.7
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
import 'dart:io';
|
||||
|
||||
class ServerResult {
|
||||
final ServerResultType type;
|
||||
final ServerImplementation? implementation;
|
||||
final Object? error;
|
||||
final StackTrace? stackTrace;
|
||||
|
||||
ServerResult(this.type, {this.error, this.stackTrace});
|
||||
ServerResult(this.type, {this.implementation, this.error, this.stackTrace});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -11,22 +14,32 @@ class ServerResult {
|
||||
}
|
||||
}
|
||||
|
||||
class ServerImplementation {
|
||||
final Process? process;
|
||||
final HttpServer? server;
|
||||
|
||||
ServerImplementation({this.process, this.server});
|
||||
}
|
||||
|
||||
enum ServerResultType {
|
||||
starting,
|
||||
startMissingHostError,
|
||||
startMissingPortError,
|
||||
startIllegalPortError,
|
||||
startFreeingPort,
|
||||
startFreePortSuccess,
|
||||
startFreePortError,
|
||||
startPingingRemote,
|
||||
startPingingLocal,
|
||||
startPingError,
|
||||
startedImplementation,
|
||||
startSuccess,
|
||||
startError,
|
||||
stopping,
|
||||
stopSuccess,
|
||||
stopError,
|
||||
missingHostError,
|
||||
missingPortError,
|
||||
illegalPortError,
|
||||
freeingPort,
|
||||
freePortSuccess,
|
||||
freePortError,
|
||||
pingingRemote,
|
||||
pingingLocal,
|
||||
pingError;
|
||||
stopError;
|
||||
|
||||
bool get isStart => name.contains("start");
|
||||
|
||||
bool get isError => name.contains("Error");
|
||||
|
||||
|
||||
@@ -15,6 +15,122 @@ final Semaphore _semaphore = Semaphore();
|
||||
String? _lastIp;
|
||||
String? _lastPort;
|
||||
|
||||
Stream<ServerResult> startBackend({required ServerType type, required String host, required String port, required bool detached, required void Function(String) onError}) async* {
|
||||
Process? process;
|
||||
HttpServer? server;
|
||||
try {
|
||||
host = host.trim();
|
||||
port = port.trim();
|
||||
if(type != ServerType.local || port != kDefaultBackendPort.toString()) {
|
||||
yield ServerResult(ServerResultType.starting);
|
||||
}
|
||||
|
||||
if (host.isEmpty) {
|
||||
yield ServerResult(ServerResultType.startMissingHostError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (port.isEmpty) {
|
||||
yield ServerResult(ServerResultType.startMissingPortError);
|
||||
return;
|
||||
}
|
||||
|
||||
final portNumber = int.tryParse(port);
|
||||
if (portNumber == null) {
|
||||
yield ServerResult(ServerResultType.startIllegalPortError);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((type != ServerType.local || port != kDefaultBackendPort.toString()) && !(await isBackendPortFree())) {
|
||||
yield ServerResult(ServerResultType.startFreeingPort);
|
||||
final result = await freeBackendPort();
|
||||
if(!result) {
|
||||
yield ServerResult(ServerResultType.startFreePortError);
|
||||
return;
|
||||
}
|
||||
|
||||
yield ServerResult(ServerResultType.startFreePortSuccess);
|
||||
}
|
||||
|
||||
switch(type){
|
||||
case ServerType.embedded:
|
||||
process = await startEmbeddedBackend(detached, onError: onError);
|
||||
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(process: process));
|
||||
break;
|
||||
case ServerType.remote:
|
||||
yield ServerResult(ServerResultType.startPingingRemote);
|
||||
final uriResult = await pingBackend(host, portNumber);
|
||||
if(uriResult == null) {
|
||||
yield ServerResult(ServerResultType.startPingError);
|
||||
return;
|
||||
}
|
||||
|
||||
server = await startRemoteBackendProxy(uriResult);
|
||||
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(server: server));
|
||||
break;
|
||||
case ServerType.local:
|
||||
if(portNumber != kDefaultBackendPort) {
|
||||
yield ServerResult(ServerResultType.startPingingLocal);
|
||||
final uriResult = await pingBackend(kDefaultBackendHost, portNumber);
|
||||
if(uriResult == null) {
|
||||
yield ServerResult(ServerResultType.startPingError);
|
||||
return;
|
||||
}
|
||||
|
||||
server = await startRemoteBackendProxy(Uri.parse("http://$kDefaultBackendHost:$port"));
|
||||
yield ServerResult(ServerResultType.startedImplementation, implementation: ServerImplementation(server: server));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
yield ServerResult(ServerResultType.startPingingLocal);
|
||||
final uriResult = await pingBackend(kDefaultBackendHost, kDefaultBackendPort);
|
||||
if(uriResult == null) {
|
||||
yield ServerResult(ServerResultType.startPingError);
|
||||
process?.kill(ProcessSignal.sigterm);
|
||||
server?.close(force: true);
|
||||
return;
|
||||
}
|
||||
|
||||
yield ServerResult(ServerResultType.startSuccess);
|
||||
}catch(error, stackTrace) {
|
||||
yield ServerResult(
|
||||
ServerResultType.startError,
|
||||
error: error,
|
||||
stackTrace: stackTrace
|
||||
);
|
||||
process?.kill(ProcessSignal.sigterm);
|
||||
server?.close(force: true);
|
||||
}
|
||||
}
|
||||
|
||||
Stream<ServerResult> stopBackend({required ServerType type, required ServerImplementation? implementation}) async* {
|
||||
yield ServerResult(ServerResultType.stopping);
|
||||
try{
|
||||
switch(type){
|
||||
case ServerType.embedded:
|
||||
final process = implementation?.process;
|
||||
if(process != null) {
|
||||
Process.killPid(process.pid, ProcessSignal.sigterm);
|
||||
}
|
||||
break;
|
||||
case ServerType.remote:
|
||||
await implementation?.server?.close(force: true);
|
||||
break;
|
||||
case ServerType.local:
|
||||
await implementation?.server?.close(force: true);
|
||||
break;
|
||||
}
|
||||
yield ServerResult(ServerResultType.stopSuccess);
|
||||
}catch(error, stackTrace){
|
||||
yield ServerResult(
|
||||
ServerResultType.stopError,
|
||||
error: error,
|
||||
stackTrace: stackTrace
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Process> startEmbeddedBackend(bool detached, {void Function(String)? onError}) async {
|
||||
final process = await startProcess(
|
||||
executable: backendStartExecutable,
|
||||
@@ -25,7 +141,9 @@ Future<Process> startEmbeddedBackend(bool detached, {void Function(String)? onEr
|
||||
log("[BACKEND] Error: $error");
|
||||
onError?.call(error);
|
||||
});
|
||||
process.exitCode.then((exitCode) => log("[BACKEND] Exit code: $exitCode"));
|
||||
if(!detached) {
|
||||
process.exitCode.then((exitCode) => log("[BACKEND] Exit code: $exitCode"));
|
||||
}
|
||||
return process;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,17 @@ import 'package:reboot_common/common.dart';
|
||||
|
||||
final File rebootBeforeS20DllFile = File("${dllsDirectory.path}\\reboot.dll");
|
||||
final File rebootAboveS20DllFile = File("${dllsDirectory.path}\\rebootS20.dll");
|
||||
|
||||
const String kRebootBelowS20DownloadUrl =
|
||||
"https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/Reboot.zip";
|
||||
const String kRebootAboveS20DownloadUrl =
|
||||
"https://nightly.link/Milxnor/Project-Reboot-3.0/workflows/msbuild/master/RebootS20.zip";
|
||||
|
||||
const String _kRebootBelowS20FallbackDownloadUrl =
|
||||
"https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootFallback.zip";
|
||||
const String _kRebootAboveS20FallbackDownloadUrl =
|
||||
"https://github.com/Auties00/reboot_launcher/raw/master/gui/dependencies/dlls/RebootS20Fallback.zip";
|
||||
|
||||
Future<bool> hasRebootDllUpdate(int? lastUpdateMs, {int hours = 24, bool force = false}) async {
|
||||
final lastUpdate = await _getLastUpdate(lastUpdateMs);
|
||||
final exists = await rebootBeforeS20DllFile.exists() && await rebootAboveS20DllFile.exists();
|
||||
@@ -45,12 +51,15 @@ Future<void> downloadDependency(InjectableDll dll, String outputPath) async {
|
||||
await output.writeAsBytes(response.bodyBytes, flush: true);
|
||||
}
|
||||
|
||||
Future<void> downloadRebootDll(File file, String url) async {
|
||||
Future<void> downloadRebootDll(File file, String url, bool aboveS20) async {
|
||||
Directory? outputDir;
|
||||
try {
|
||||
final response = await http.get(Uri.parse(url));
|
||||
var response = await http.get(Uri.parse(url));
|
||||
if(response.statusCode != 200) {
|
||||
throw Exception("Cannot download reboot.zip: status code ${response.statusCode}");
|
||||
response = await http.get(Uri.parse(aboveS20 ? _kRebootAboveS20FallbackDownloadUrl : _kRebootBelowS20FallbackDownloadUrl));
|
||||
if(response.statusCode != 200) {
|
||||
throw Exception("status code ${response.statusCode}");
|
||||
}
|
||||
}
|
||||
|
||||
outputDir = await installationDirectory.createTemp("reboot_out");
|
||||
|
||||
@@ -168,20 +168,6 @@ bool resume(int pid) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Future<void> watchProcess(int pid) => Isolate.run(() {
|
||||
final processHandle = OpenProcess(FILE_ACCESS_RIGHTS.SYNCHRONIZE, FALSE, pid);
|
||||
if (processHandle == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
WaitForSingleObject(processHandle, INFINITE);
|
||||
}finally {
|
||||
CloseHandle(processHandle);
|
||||
}
|
||||
});
|
||||
|
||||
List<String> createRebootArgs(String username, String password, bool host, GameServerType hostType, bool logging, String additionalArgs) {
|
||||
log("[PROCESS] Generating reboot args");
|
||||
if(password.isEmpty) {
|
||||
@@ -292,16 +278,8 @@ final class _ExtendedProcess implements Process {
|
||||
_stdout = attached ? delegate.stdout.asBroadcastStream() : null,
|
||||
_stderr = attached ? delegate.stderr.asBroadcastStream() : null;
|
||||
|
||||
|
||||
@override
|
||||
Future<int> get exitCode {
|
||||
try {
|
||||
return _delegate.exitCode;
|
||||
}catch(_) {
|
||||
return watchProcess(_delegate.pid)
|
||||
.then((_) => -1);
|
||||
}
|
||||
}
|
||||
Future<int> get exitCode => _delegate.exitCode;
|
||||
|
||||
@override
|
||||
bool kill([ProcessSignal signal = ProcessSignal.sigterm]) => _delegate.kill(signal);
|
||||
|
||||
Reference in New Issue
Block a user