// @lint-ignore-every LICENSELINT // Copyright Epic Games, Inc. All Rights Reserved. #include "OculusXRSyntheticEnvironmentServer.h" #include "OculusXRSimulator.h" #if PLATFORM_WINDOWS #include "HAL/FileManager.h" #include "Internationalization/Regex.h" #include "OculusXRHMDRuntimeSettings.h" #include "OculusXRTelemetryEvents.h" #include "Misc/FileHelper.h" #include "Misc/MessageDialog.h" #include "Windows/WindowsPlatformMisc.h" const FString SynthEnvServer = "Synthetic Environment Server"; const FString LocalSharingServer = "Local Sharing Server"; FProcHandle FMetaXRSES::EnvProcHandle; FProcHandle FMetaXRSES::LSSProcHandle; void FMetaXRSES::StopServer() { StopProcess(EnvProcHandle, SynthEnvServer); StopProcess(LSSProcHandle, LocalSharingServer); } void FMetaXRSES::LaunchEnvironment(int32 EnvironmentIndex) { const FString EnvironmentName = SynthEnvRooms[EnvironmentIndex].SynthName; const FString SESPath = SynthEnvRooms[EnvironmentIndex].Executable; if (FMetaXRSimulator::GetPackagePath().IsEmpty() || SESPath.IsEmpty() || EnvironmentName.IsEmpty()) { return; } StopServer(); OculusXRTelemetry::TScopedMarker Event; const bool bLaunched = LaunchProcess(SESPath, EnvironmentName, LocalSharingServer, EnvProcHandle); const auto& _ = Event.SetResult(bLaunched ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail).AddAnnotation("launch", StringCast(*EnvironmentName).Get()); LaunchLocalSharingServer(); } void FMetaXRSES::LaunchLocalSharingServer() { OculusXRTelemetry::TScopedMarker Event; FString LSSPath = GetLocalSharingServerPath(); const bool bLaunched = LaunchProcess(LSSPath, "", LocalSharingServer, LSSProcHandle); const auto& _ = Event.SetResult(bLaunched ? OculusXRTelemetry::EAction::Success : OculusXRTelemetry::EAction::Fail).AddAnnotation("launch", "localsharingserver"); } bool FMetaXRSES::LaunchProcess(FString BinaryPath, FString Arguments, FString LogContext, FProcHandle& OutProcHandle) { if (!IFileManager::Get().FileExists(*BinaryPath)) { UE_LOG(LogMetaXRSES, Error, TEXT("Failed to find %s."), *BinaryPath); return false; } UE_LOG(LogMetaXRSES, Log, TEXT("Launching %s."), *BinaryPath); uint32 OutProcessId = 0; OutProcHandle = FPlatformProcess::CreateProc(*BinaryPath, *Arguments, false, false, false, &OutProcessId, 0, NULL, NULL); if (!OutProcHandle.IsValid()) { UE_LOG(LogMetaXRSES, Error, TEXT("Failed to launch %s."), *BinaryPath); FPlatformProcess::CloseProc(OutProcHandle); return false; } UE_LOG(LogMetaXRSES, Log, TEXT("Launched %s."), *BinaryPath); return true; } void FMetaXRSES::StopProcess(FProcHandle& ProcHandle, FString LogContext) { if (ProcHandle.IsValid()) { if (FPlatformProcess::IsProcRunning(ProcHandle)) { UE_LOG(LogMetaXRSES, Log, TEXT("Stopping %s."), *LogContext); FPlatformProcess::TerminateProc(ProcHandle); } FPlatformProcess::CloseProc(ProcHandle); } else { UE_LOG(LogMetaXRSES, Warning, TEXT("Failed to stop process %s because it is not active anymore."), *LogContext); } } TArray FMetaXRSES::SynthEnvRooms = {}; bool FMetaXRSES::SynthEnvParsed = false; TArray GatherServers(const FString& path) { TArray servers{}; TArray batFiles{}; const FString ext("bat"); IFileManager::Get().FindFiles(batFiles, *path, *ext); const static FRegexPattern pattern(TEXT("start (\\S+) (\\S+)")); for (const FString& stem : batFiles) { const FString file = path + "/" + stem; FString result; if (!FFileHelper::LoadFileToString(result, *file)) { continue; } FRegexMatcher matcher(pattern, result); if (!matcher.FindNext()) { continue; } UE_LOG(LogMetaXRSES, Warning, TEXT("In %s, found %s && %s"), *file, *matcher.GetCaptureGroup(1), *matcher.GetCaptureGroup(2)); FString left; stem.Split(TEXT("."), &left, NULL); auto absPath = path + "/" + matcher.GetCaptureGroup(1); servers.Push({ left, matcher.GetCaptureGroup(2), IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(absPath.GetCharArray().GetData()) }); } return servers; } TArray& FMetaXRSES::GetSynthEnvRooms() { if (SynthEnvParsed) { return SynthEnvRooms; } SynthEnvRooms = {}; FString dirPath = FMetaXRSimulator::GetPackagePath(); if (dirPath.IsEmpty()) { return SynthEnvRooms; } TArray dirNames; IFileManager::Get().IterateDirectory(dirPath.GetCharArray().GetData(), [&dirNames](const TCHAR* name, bool) -> bool { dirNames.Add(name); return true; }); for (auto dir : dirNames) { // find all of the servers in the subdirectories SynthEnvRooms.Append(GatherServers(dir)); } SynthEnvParsed = true; return SynthEnvRooms; } FString FMetaXRSES::GetLocalSharingServerPath() { FString Path = FMetaXRSimulator::GetPackagePath() + "/local_sharing_server~/local_sharing_server.exe"; if (!IFileManager::Get().FileExists(*Path)) { UE_LOG(LogMetaXRSES, Warning, TEXT("Failed to find %s, trying the previous version"), *Path); Path = FMetaXRSimulator::GetPackagePath() + "/.local_sharing_server/local_sharing_server.exe"; if (!IFileManager::Get().FileExists(*Path)) { UE_LOG(LogMetaXRSES, Error, TEXT("Failed to find LocalSharingServer, giving up")); Path = ""; } } return Path; } #endif