Select Git revision
streamlit_app.py
-
Leah Tacke genannt Unterberg authoredLeah Tacke genannt Unterberg authored
VAServerLauncher.cpp 10.18 KiB
#include "VAServerLauncher.h"
#include <string>
#include "Misc/FileHelper.h"
#include "SocketSubsystem.h"
#include "GeneralProjectSettings.h"
#include "Utility/VirtualRealityUtilities.h"
#include "VAUtils.h"
#include "VASettings.h"
#include "VAPlugin.h"
bool FVAServerLauncher::RemoteStartVAServer(const FString& Host, const int Port, const FString& VersionName)
{
if (!UVirtualRealityUtilities::IsMaster())
{
return false;
}
if (VAServerLauncherSocket != nullptr)
{
return true;
}
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Try to remotely start the VAServer at address " +
Host + ":" + FString::FromInt(Port) + " for version: " + VersionName, false);
//Connect
const FString SocketName(TEXT("VAServerStarterConnection"));
VAServerLauncherSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(
NAME_Stream, SocketName, false);
TSharedPtr<FInternetAddr> InternetAddress = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
bool bValidIP;
InternetAddress->SetIp(*Host, bValidIP);
InternetAddress->SetPort(Port);
if (!bValidIP)
{
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: The Ip cannot be parsed!", true);
return false;
}
if (VAServerLauncherSocket == nullptr || !VAServerLauncherSocket->Connect(*InternetAddress))
{
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Cannot connect to Launcher!", true);
return false;
}
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Successfully connected to Launcher", false);
//Send requested version
TArray<uint8> RequestData = ConvertString(VersionName);
int BytesSend = 0;
VAServerLauncherSocket->Send(RequestData.GetData(), RequestData.Num(), BytesSend);
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Send " + FString::FromInt(BytesSend) +
" bytes to the VAServer Launcher, with version name: " + VersionName + " Waiting for answer.", false);
//Receive response
const int32 BufferSize = 16;
int32 BytesRead = 0;
uint8 Response[16];
if (VAServerLauncherSocket->Recv(Response, BufferSize, BytesRead) && BytesRead == 1)
{
switch (Response[0])
{
case 'g':
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Received go from launcher, VAServer seems to be correctly started.", false);
break;
case 'n':
FVAUtils::OpenMessageBox("[FVAServerLauncher::RemoteStartVAServer()]: VAServer cannot be launched, invalid VAServer binary file or cannot be found",
true);
VAServerLauncherSocket = nullptr;
return false;
case 'i':
FVAUtils::OpenMessageBox("[FVAServerLauncher::RemoteStartVAServer()]: VAServer cannot be launched, invalid file entry in the config", true);
VAServerLauncherSocket = nullptr;
return false;
case 'a':
FVAUtils::OpenMessageBox("[FVAServerLauncher::RemoteStartVAServer()]: VAServer was aborted", true);
VAServerLauncherSocket = nullptr;
return false;
case 'f':
FVAUtils::OpenMessageBox("[FVAServerLauncher::RemoteStartVAServer()]: VAServer cannot be launched, requested version \"" +
VersionName + "\" is not available/specified", true);
VAServerLauncherSocket = nullptr;
return false;
default:
FVAUtils::OpenMessageBox("[FVAServerLauncher::RemoteStartVAServer()]: Unexpected response from VAServer Launcher: " +
FString(reinterpret_cast<char*>(&Response[0])), true);
VAServerLauncherSocket = nullptr;
return false;
}
}
else
{
FVAUtils::LogStuff("[FVAServerLauncher::RemoteStartVAServer()]: Error while receiving response from VAServer Launcher", true);
VAServerLauncherSocket = nullptr;
return false;
}
return true;
}
bool FVAServerLauncher::StartVAServerLauncher()
{
//check whether we can also start the VSServer Launcher python script.
if (!UVirtualRealityUtilities::IsMaster())
{
return false;
}
const UVASettings* Settings = GetDefault<UVASettings>();
FString LauncherScriptDir = Settings->VALauncherPath;
if(FPaths::IsRelative(LauncherScriptDir))
{
FString ProjectDir = FPaths::ProjectDir();
ProjectDir = IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*ProjectDir);
LauncherScriptDir = FPaths::ConvertRelativePathToFull(ProjectDir, LauncherScriptDir);
}
LauncherScriptDir = FPaths::Combine(LauncherScriptDir, TEXT("LaunchScript"));
FString LauncherScript = TEXT("VirtualAcousticsStarterServer.py");
if (FPaths::FileExists(FPaths::Combine(LauncherScriptDir, LauncherScript)))
{
FString CMDCommand = "cd/d " + LauncherScriptDir + " & ";
//check whether py or python exist
auto DoesCommandExist = [&](FString Command)
{
//this checks whether a given command returns a result
FString TmpCmdResultFile = "tmpPyVersion.txt";
TmpCmdResultFile = FPaths::Combine(LauncherScriptDir, TmpCmdResultFile);
Command = Command + " >> " + TmpCmdResultFile;
system(TCHAR_TO_ANSI(*Command));
FString Result;
FFileHelper::LoadFileToString(Result, *TmpCmdResultFile);
IFileManager::Get().Delete(*TmpCmdResultFile);
return !Result.IsEmpty();
};
bool bPyExists = DoesCommandExist("py --version");
bool bPythonExists = DoesCommandExist("python --version");
if(bPythonExists || bPyExists)
{
FString Command = CMDCommand + "start " + (bPythonExists?"python":"py") + " " + LauncherScript;
system(TCHAR_TO_ANSI(*Command));
return true;
}
else
{
FVAUtils::OpenMessageBox("VA Launcher cannot be started since neither \"py\" nor \"python\" can be found. If it is installed add it to PATH (and restart Visual Studio)", true);
return false;
}
}
else
{
FVAUtils::LogStuff("[FVAServerLauncher::StartVAServerLauncher] Unable to automatically start the launcher script, looked for "+LauncherScript+" at "+LauncherScriptDir+". If you want to use this convenience function change the VALauncher Path in the Engine/Virtual Acoustics(VA) section of the project settings. However, nothing bad will happen without.");
}
return false;
}
bool FVAServerLauncher::SendFileToVAServer(const FString& RelativeFilename)
{
if (!UVirtualRealityUtilities::IsMaster())
{
return false;
}
if(VAServerLauncherSocket==nullptr)
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: No connection to VAServer Starter, so no files can be send to VAServer!", true);
return false;
}
if(!GetDefault<UVASettings>()->VALauncherCopyFiles)
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: Setting to not send files over the network to VAServer is set, so not sending anything!", false);
return false;
}
if(!FPaths::FileExists(FPaths::Combine(FPaths::ProjectContentDir(),RelativeFilename)))
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: File to send("+RelativeFilename+") could not be found and therefore not send!", true);
return false;
}
TArray<uint8> FileBinaryArray;
FFileHelper::LoadFileToArray(FileBinaryArray, *FPaths::Combine(FPaths::ProjectContentDir(),RelativeFilename));
const FString ProjectName = GetDefault<UGeneralProjectSettings>()->ProjectName;
FString MetaInfo = "file:"+RelativeFilename+":"+FString::FromInt(FileBinaryArray.Num())+":"+ProjectName;
TArray<uint8> MetaInfoBinary = ConvertString(MetaInfo);
int32 BytesSend;
VAServerLauncherSocket->Send(MetaInfoBinary.GetData(), MetaInfoBinary.Num(), BytesSend);
//Receive response
const int32 BufferSize = 16;
int32 BytesRead = 0;
uint8 Response[16];
if (VAServerLauncherSocket->Recv(Response, BufferSize, BytesRead))
{
FString ResponseString = ByteArrayToString(Response, BytesRead);
if(ResponseString=="ack"){
//VAServer waits for file
int32 BytesAlreadySend = 0;
while(BytesAlreadySend<FileBinaryArray.Num())
{
//send 1024 byte packages
int32 BytesToSend = (FileBinaryArray.Num()-BytesAlreadySend>1024?1024:FileBinaryArray.Num()-BytesAlreadySend);
VAServerLauncherSocket->Send(&FileBinaryArray[BytesAlreadySend],BytesToSend, BytesSend);
BytesAlreadySend += BytesSend;
}
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: Entire file ("+RelativeFilename+") send!", false);
VAServerLauncherSocket->Recv(Response, BufferSize, BytesRead);
if(BytesRead==3 && Response[0]=='a' && Response[1]=='c' && Response[2]=='k')
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: File was received by VAServerLauncher successfully!", false);
//the search path is added potenitally multiple times, but can only be added once the folder is created (which the above guarantees)
const std::string SearchPath = "../tmp/" + std::string(TCHAR_TO_UTF8(*GetDefault<UGeneralProjectSettings>()->ProjectName));
FVAPlugin::AddVAServerSearchPath(SearchPath);
}
else
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: File was NOT received by VAServerLauncher!", true);
return false;
}
}
else if (ResponseString=="exists"){
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: File already exists with same size, no need ro re-send!", false);
}
else
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: Server Launcher does not want to receive a file, answer: "+ResponseString, true);
return false;
}
}
else
{
FVAUtils::LogStuff("[FVAServerLauncher::SendFileToVAServer()]: Server Launcher does not want to receive a file, no answer!", true);
return false;
}
//the search path is added in any case once after connecting to a new server
return true;
}
void FVAServerLauncher::ReleaseVAServerLauncherConnection()
{
if (!UVirtualRealityUtilities::IsMaster())
{
return;
}
if(VAServerLauncherSocket!=nullptr){
VAServerLauncherSocket->Close();
VAServerLauncherSocket = nullptr;
}
}
bool FVAServerLauncher::IsVAServerLauncherConnected()
{
return VAServerLauncherSocket!=nullptr;
}
TArray<uint8> FVAServerLauncher::ConvertString(const FString& String)
{
TArray<uint8> RequestData;
for (TCHAR Character : String.GetCharArray())
{
const uint8 InByte = static_cast<uint8>(Character);
if (InByte != 0)
{
RequestData.Add(static_cast<uint8>(Character));
}
}
return RequestData;
}
FString FVAServerLauncher::ByteArrayToString(const uint8* In, int32 Count)
{
FString Result;
Result.Empty(Count);
while (Count)
{
// Put the byte into an int16
int16 Value = *In;
Result += TCHAR(Value);
++In;
Count--;
}
return Result;
}