Files
UnrealEngineUWP/Engine/Source/Developer/CookOnTheFlyNetServer/Private/CookOnTheFlyNetServerBase.cpp
dan engelbrecht db5e568754 Game client no longer needs -zenstoreproject or -zenstorehost arguments to correctly run with a COTF server which uses Zen.
Game client now accepts only -filehostip for connection to a CTOF server, -cookonthefly is no longer necessary and is ignored.
Game client will now receive ProjectName (ProjectId), Platform (OplogId), Zen server host name and port from COTF server if running with zenstore.
Fixed issues with generating the ProjectId from a path where drive letters where lower case.

#rb zousar.shaker pj.kack
#preflight

[CL 24889513 by dan engelbrecht in ue5-main branch]
2023-04-03 01:51:40 -04:00

177 lines
5.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "CookOnTheFlyNetServerBase.h"
#include "Serialization/BufferArchive.h"
#include "Interfaces/ITargetPlatform.h"
#include "Serialization/ArrayReader.h"
#include "HAL/RunnableThread.h"
FCookOnTheFlyClientConnectionBase::FCookOnTheFlyClientConnectionBase(FCookOnTheFlyNetworkServerBase& InOwner)
: Owner(InOwner)
{
}
FCookOnTheFlyClientConnectionBase::~FCookOnTheFlyClientConnectionBase()
{
if (WorkerThread)
{
delete WorkerThread;
}
if (bClientConnectedBroadcasted && Owner.ClientDisconnectedEvent.IsBound())
{
Owner.ClientDisconnectedEvent.Broadcast(*this);
}
}
bool FCookOnTheFlyClientConnectionBase::Initialize()
{
FArrayReader HandshakeRequestPayload;
if (!ReceivePayload(HandshakeRequestPayload))
{
UE_LOG(LogCookOnTheFlyNetworkServer, Warning, TEXT("Failed to receive handshake payload"));
return false;
}
TArray<FString> TargetPlatformNames;
HandshakeRequestPayload << TargetPlatformNames;
HandshakeRequestPayload << bIsSingleThreaded;
bool bIsOk = true;
FString PlatformNameString;
if (!TargetPlatformNames.IsEmpty())
{
// figure out the best matching target platform for the set of valid ones
for (int32 TPIndex = 0; TPIndex < TargetPlatformNames.Num() && !TargetPlatform; TPIndex++)
{
UE_LOG(LogCookOnTheFlyNetworkServer, Verbose, TEXT(" Possible Target Platform from client: %s"), *TargetPlatformNames[TPIndex]);
// look for a matching target platform
for (int32 ActiveTPIndex = 0; ActiveTPIndex < Owner.ActiveTargetPlatforms.Num(); ActiveTPIndex++)
{
UE_LOG(LogCookOnTheFlyNetworkServer, Verbose, TEXT(" Checking against: %s"), *Owner.ActiveTargetPlatforms[ActiveTPIndex]->PlatformName());
if (Owner.ActiveTargetPlatforms[ActiveTPIndex]->PlatformName() == TargetPlatformNames[TPIndex])
{
TargetPlatform = Owner.ActiveTargetPlatforms[ActiveTPIndex];
PlatformNameString = TargetPlatform->PlatformName();
PlatformName = FName(PlatformNameString);
break;
}
}
}
// if we didn't find one, reject client and also print some warnings
if (!TargetPlatform)
{
// reject client we can't cook/compile shaders for you!
UE_LOG(LogCookOnTheFlyNetworkServer, Warning, TEXT("Unable to find target platform for client, terminating client connection!"));
for (int32 TPIndex = 0; TPIndex < TargetPlatformNames.Num(); TPIndex++)
{
UE_LOG(LogCookOnTheFlyNetworkServer, Warning, TEXT(" Target platforms from client: %s"), *TargetPlatformNames[TPIndex]);
}
for (int32 ActiveTPIndex = 0; ActiveTPIndex < Owner.ActiveTargetPlatforms.Num(); ActiveTPIndex++)
{
UE_LOG(LogCookOnTheFlyNetworkServer, Warning, TEXT(" Active target platforms on server: %s"), *Owner.ActiveTargetPlatforms[ActiveTPIndex]->PlatformName());
}
bIsOk = false;
}
}
if (!bIsOk)
{
return false;
}
if (Owner.ClientConnectedEvent.IsBound())
{
Owner.ClientConnectedEvent.Broadcast(*this);
bClientConnectedBroadcasted = true;
}
FBufferArchive HandshakeResponsePayload;
HandshakeResponsePayload << bIsOk;
HandshakeResponsePayload << PlatformNameString;
HandshakeResponsePayload << ZenProjectId;
HandshakeResponsePayload << ZenHostName;
HandshakeResponsePayload << ZenHostPort;
if (!SendPayload(HandshakeResponsePayload))
{
return false;
}
#if UE_BUILD_DEBUG
// this thread needs more space in debug builds as it tries to log messages and such
const static uint32 ThreadSize = 2 * 1024 * 1024;
#else
const static uint32 ThreadSize = 1 * 1024 * 1024;
#endif
WorkerThread = FRunnableThread::Create(this, TEXT("FCookOnTheFlyClientConnection"), ThreadSize, TPri_AboveNormal);
return true;
}
uint32 FCookOnTheFlyClientConnectionBase::Run()
{
while (!bStopRequested)
{
// read a header and payload pair
FArrayReader Payload;
if (!ReceivePayload(Payload))
{
UE_LOG(LogCookOnTheFlyNetworkServer, Warning, TEXT("ReceivePayload failed"));
break;
}
ProcessPayload(Payload);
}
return 0;
}
bool FCookOnTheFlyClientConnectionBase::ProcessPayload(FArchive& Payload)
{
using namespace UE::Cook;
FCookOnTheFlyRequest Request;
Payload << Request;
return Owner.ProcessRequest(*this, Request);
}
bool FCookOnTheFlyClientConnectionBase::SendMessage(const UE::Cook::FCookOnTheFlyMessage& Message)
{
FBufferArchive Payload;
Payload.Reserve(IntCastChecked<int32>(Message.TotalSize()));
Payload << const_cast<UE::Cook::FCookOnTheFlyMessage&>(Message);
return SendPayload(Payload);
}
FCookOnTheFlyNetworkServerBase::FCookOnTheFlyNetworkServerBase(const TArray<ITargetPlatform*>& InActiveTargetPlatforms)
: ActiveTargetPlatforms(InActiveTargetPlatforms)
{
}
bool FCookOnTheFlyNetworkServerBase::ProcessRequest(FCookOnTheFlyClientConnectionBase& Connection, const UE::Cook::FCookOnTheFlyRequest& Request)
{
using namespace UE::Cook;
ECookOnTheFlyMessage RequestType = Request.GetMessageType();
FHandleRequestDelegate* Handler = Handlers.Find(RequestType);
if (!Handler)
{
return false;
}
if (!Handler->IsBound())
{
return false;
}
return Handler->Execute(Connection, Request);
}
UE::Cook::ICookOnTheFlyNetworkServer::FHandleRequestDelegate& FCookOnTheFlyNetworkServerBase::OnRequest(UE::Cook::ECookOnTheFlyMessage MessageType)
{
FHandleRequestDelegate& Handler = Handlers.FindOrAdd(MessageType);
return Handler;
}