Files
GacUI/Import-Test/Test.RemotingHelpers.h
2026-08-30 18:03:19 -07:00

521 lines
15 KiB
C++

/***********************************************************************
THIS FILE IS AUTOMATICALLY GENERATED. DO NOT MODIFY
DEVELOPER: Zihan Chen(vczh)
***********************************************************************/
#include "GacUI.h"
#include "Vlpp.h"
#include "VlppGlrParser.h"
#include "VlppOS.h"
#include "VlppReflection.h"
#include "VlppRegex.h"
#include "VlppWorkflowLibrary.h"
/***********************************************************************
.\REMOTINGSERVER\REMOTINGCHANNELSERVER.H
***********************************************************************/
#ifndef VCZH_PRESENTATION_REMOTING_REMOTINGCHANNELSERVER
#define VCZH_PRESENTATION_REMOTING_REMOTINGCHANNELSERVER
namespace vl::presentation::remoting
{
using JsonChannelClient = remoteprotocol::channeling::IJsonChannelClient;
using JsonChannel = remoteprotocol::channeling::IJsonChannel;
using JsonChannelServer = remoteprotocol::channeling::IJsonChannelServer;
inline bool IsRendererChannel(const JsonChannelClient::ChannelNameList& availableChannels)
{
return
availableChannels.Count() == 1 &&
availableChannels[0] == WString::Unmanaged(remoteprotocol::channeling::GacUIRemoteProtocolChannelName);
}
template<typename TServerBase>
class RemotingChannelServer
: public remoteprotocol::channeling::GuiRemoteProtocolNetworkChannelServer<TServerBase>
{
using Base = remoteprotocol::channeling::GuiRemoteProtocolNetworkChannelServer<TServerBase>;
using CoreChannel = remoteprotocol::channeling::GuiRemoteProtocolCoreChannel;
private:
SpinLock lockConnection;
JsonChannel* coreJsonChannel = nullptr;
CoreChannel* coreProtocolChannel = nullptr;
bool acceptRenderer = false;
vint rendererClientId = -1;
protected:
virtual inter_process::WaitForClientResult OnRemoteClientConnected(
vint clientId,
const JsonChannelClient::ChannelNameList& availableChannels
)
{
using WaitForClientResult = inter_process::WaitForClientResult;
auto rendererChannel = IsRendererChannel(availableChannels);
if (acceptRenderer && rendererChannel)
{
JsonChannel* jsonChannelToOldRenderer = nullptr;
vint oldRendererClientId = -1;
SPIN_LOCK(lockConnection)
{
if (clientId == rendererClientId)
{
return WaitForClientResult::Reject;
}
oldRendererClientId = rendererClientId;
rendererClientId = clientId;
if (oldRendererClientId != -1)
{
jsonChannelToOldRenderer = coreJsonChannel;
if (coreProtocolChannel)
{
coreProtocolChannel->DetachRenderer(oldRendererClientId);
}
}
}
if (oldRendererClientId != -1)
{
bool rendererNotifiedToStop = false;
if (jsonChannelToOldRenderer)
{
try
{
Ptr<glr::json::JsonObject> package;
remoteprotocol::channeling::ChannelPackageInfo info
{
remoteprotocol::channeling::ChannelPackageSemantic::Message,
-1,
WString::Unmanaged(L"ControllerConnectionStopped")
};
remoteprotocol::channeling::JsonChannelPack(info, {}, package);
jsonChannelToOldRenderer->SendToClient(oldRendererClientId, package);
bool disconnected = false;
jsonChannelToOldRenderer->BatchWrite(disconnected);
rendererNotifiedToStop = !disconnected;
}
catch (const Error&)
{
}
catch (const Exception&)
{
}
}
if (!rendererNotifiedToStop)
{
this->DisconnectClient(oldRendererClientId);
}
}
return WaitForClientResult::Accept;
}
return WaitForClientResult::Reject;
}
public:
using Base::OnClientConnected;
template<typename... TArgs>
RemotingChannelServer(
Ptr<glr::json::Parser> parser,
bool _acceptRenderer,
TArgs&&... args
)
: Base(parser, std::forward<TArgs>(args)...)
, acceptRenderer(_acceptRenderer)
{
}
void SetCoreChannels(
JsonChannel* jsonChannel,
CoreChannel* protocolChannel
)
{
SPIN_LOCK(lockConnection)
{
coreJsonChannel = jsonChannel;
coreProtocolChannel = protocolChannel;
}
}
void ClearCoreChannels()
{
SPIN_LOCK(lockConnection)
{
coreProtocolChannel = nullptr;
coreJsonChannel = nullptr;
}
}
vint GetRendererClientId()
{
vint clientId = -1;
SPIN_LOCK(lockConnection)
{
clientId = rendererClientId;
}
return clientId;
}
inter_process::WaitForClientResult OnClientConnected(
vint clientId,
const JsonChannelClient::ChannelNameList& availableChannels,
Ptr<JsonChannelClient> localClient
) override
{
if (localClient)
{
return inter_process::WaitForClientResult::Accept;
}
return OnRemoteClientConnected(clientId, availableChannels);
}
void OnClientDisconnected(vint clientId) override
{
SPIN_LOCK(lockConnection)
{
if (rendererClientId == clientId)
{
rendererClientId = -1;
if (coreProtocolChannel)
{
coreProtocolChannel->DetachRenderer(clientId);
}
}
}
}
};
}
#endif
/***********************************************************************
.\RENDERERCLIENT\REMOTEPROTOCOLRENDERERCLIENT.H
***********************************************************************/
#ifndef VCZH_PRESENTATION_REMOTING_REMOTEPROTOCOLRENDERERCLIENT
#define VCZH_PRESENTATION_REMOTING_REMOTEPROTOCOLRENDERERCLIENT
namespace vl::presentation::remoting
{
class RemoteProtocolRendererClient : public remoteprotocol::channeling::GuiRemoteProtocolChannelClient
{
using Base = remoteprotocol::channeling::GuiRemoteProtocolChannelClient;
using AsyncJsonChannelRenderer = remoteprotocol::channeling::GuiRemoteProtocolAsyncJsonChannelRenderer;
private:
SpinLock lockState;
WString fatalTitle;
bool triggeredFatalError = false;
bool retainedFatalError = false;
bool stopping = false;
remote_renderer::GuiRemoteRendererSingle* renderer = nullptr;
AsyncJsonChannelRenderer* asyncRendererChannel = nullptr;
AutomationServiceRenderer* rendererAutomationService = nullptr;
void QueueMainThreadTask(const Func<void()>& task);
void ProcessFatalError(const WString& errorMessage);
void ProcessDisconnected();
public:
RemoteProtocolRendererClient(
Ptr<inter_process::INetworkProtocolClient> client,
Ptr<glr::json::Parser> parser,
const WString& fatalTitle
);
void SetRenderer(remote_renderer::GuiRemoteRendererSingle* renderer);
void SetAsyncRendererChannel(
remoteprotocol::channeling::GuiRemoteProtocolAsyncJsonChannelRenderer* asyncRendererChannel
);
void SetRendererAutomationService(AutomationServiceRenderer* automationService);
void BeginStopping();
bool IsFatalErrorRetained();
void OnReadError(const WString& errorMessage) override;
void OnLocalError(const WString& errorMessage, bool fatal) override;
void OnDisconnected() override;
};
}
#endif
/***********************************************************************
.\RVMT\VIEWMODELSHARED.H
***********************************************************************/
#ifndef VCZH_PRESENTATION_RVMT_VIEWMODEL_SHARED
#define VCZH_PRESENTATION_RVMT_VIEWMODEL_SHARED
namespace vl::presentation::remoting
{
using JsonPackage = rpc_controller::channeling::JsonPackage;
using JsonChannel = rpc_controller::channeling::JsonChannel;
using JsonChannelClient = rpc_controller::channeling::JsonChannelClient;
using JsonChannelServer = rpc_controller::channeling::JsonChannelServer;
using JsonLocalChannelClient = rpc_controller::channeling::JsonLocalChannelClient;
using TaskQueue = rpc_controller::channeling::TaskQueue;
using RpcDispatcherClient = rpc_controller::channeling::RpcJsonDispatcherClientForTaskQueue;
inline constexpr const wchar_t* ViewModelChannelName = L"ViewModelChannel";
inline constexpr const wchar_t* ViewModelReadyChannelName = L"ViewModelReadyChannel";
inline constexpr const wchar_t* ViewModelReadyMessage = L"Ready";
inline constexpr const wchar_t* RemoteViewModelHostDisconnectedError = L"RemotingTest_RvmHost disconnected.";
inline constexpr vint InvalidRemoteViewModelClientId = -1;
inline JsonPackage CreateViewModelReadyMessage()
{
auto package = Ptr(new glr::json::JsonString);
package->content.value = ViewModelReadyMessage;
return package;
}
inline bool IsViewModelReadyMessage(const JsonPackage& package)
{
auto jsonString = package.Cast<glr::json::JsonString>();
return jsonString && jsonString->content.value == ViewModelReadyMessage;
}
}
#endif
/***********************************************************************
.\RVMT\VIEWMODELHOSTCLIENT.H
***********************************************************************/
#ifndef VCZH_PRESENTATION_RVMT_VIEWMODEL_HOST_CLIENT
#define VCZH_PRESENTATION_RVMT_VIEWMODEL_HOST_CLIENT
namespace vl::presentation::remoting
{
class ViewModelHostClient
: public rpc_controller::channeling::JsonNetworkChannelClient
{
private:
JsonChannelClient::ChannelMap channelNames;
Ptr<RpcDispatcherClient> dispatcher;
JsonChannel* controlChannel = nullptr;
public:
ViewModelHostClient(
Ptr<inter_process::INetworkProtocolClient> networkClient,
Ptr<glr::json::Parser> parser,
Ptr<TaskQueue> taskQueue
);
const JsonChannelClient::ChannelNameList& OnGetChannelNames() override;
void OnConnected(vint clientId) override;
void OnDisconnected() override;
void OnReadError(const WString& errorMessage) override;
void OnLocalError(const WString& errorMessage, bool fatal) override;
void Connect();
void SendReady();
RpcDispatcherClient* GetDispatcher();
};
}
#endif
/***********************************************************************
.\RVMT\VIEWMODELHOSTSERVER.H
***********************************************************************/
#ifndef VCZH_PRESENTATION_RVMT_VIEWMODEL_HOST_SERVER
#define VCZH_PRESENTATION_RVMT_VIEWMODEL_HOST_SERVER
namespace vl::presentation::remoting
{
class TaskQueueThread;
class RpcBroadcastingLocalClient;
class RpcServiceAccessLocalClient;
class RpcServerHelpers
{
private:
enum class RequesterPhase
{
Starting,
Running,
Stopping,
};
// covers phase, host state, admissionReady, taskQueueStarted, rpcInitialized, brokerDispatcher, requesterDispatcher and pending host-loss state
SpinLock lockState;
CriticalSection lockBroker;
RequesterPhase phase;
vint hostId = InvalidRemoteViewModelClientId;
bool hostEverAccepted = false;
bool brokerRegistrationClaimed = false;
bool admissionReady = false;
bool taskQueueStarted = false;
bool rpcInitialized = false;
bool pendingHostLoss = false;
bool hostLossClaimed = false;
rpc_controller::channeling::RpcJsonDispatcherServer* brokerDispatcher = nullptr;
JsonChannelServer* channelServer = nullptr;
Ptr<TaskQueue> taskQueue;
Ptr<TaskQueueThread> taskQueueThread;
Ptr<RpcBroadcastingLocalClient> broadcastingClient;
Ptr<RpcServiceAccessLocalClient> requesterClient;
RpcDispatcherClient* requesterDispatcher = nullptr;
void RegisterHost(vint clientId);
void OnControlMessage(vint senderClientId, const JsonPackage& package);
void FinalizeRpcOnTaskQueue();
bool BeginRunning();
void BeginStopping();
protected:
RpcServerHelpers(Ptr<glr::json::Parser> parser);
~RpcServerHelpers();
bool TryAcceptHost(vint clientId);
void OnClientDisconnected(vint clientId);
void Start(JsonChannelServer* channelServer);
vint Connect(const collections::List<WString>& requiredServiceNames);
RpcDispatcherClient* GetDispatcher();
Ptr<IDescriptable> RequestService(const WString& typeName);
bool CanAdmitRenderer();
void Stop(const Func<void()>& stopServer);
};
}
namespace vl::presentation::remote_view_model_test
{
template<typename TServerBase>
class RemoteViewModelChannelServer
: public remoting::RemotingChannelServer<TServerBase>
, protected remoting::RpcServerHelpers
{
using Base = remoting::RemotingChannelServer<TServerBase>;
using Helpers = remoting::RpcServerHelpers;
protected:
bool IsRemoteViewModelHostChannel(
const remoting::JsonChannelClient::ChannelNameList& availableChannels
)
{
return
availableChannels.Count() == 2 &&
availableChannels.IndexOf(WString::Unmanaged(remoting::ViewModelChannelName)) != -1 &&
availableChannels.IndexOf(WString::Unmanaged(remoting::ViewModelReadyChannelName)) != -1;
}
inter_process::WaitForClientResult OnRemoteClientConnected(
vint clientId,
const remoting::JsonChannelClient::ChannelNameList& availableChannels
) override
{
using WaitForClientResult = inter_process::WaitForClientResult;
if (IsRemoteViewModelHostChannel(availableChannels))
{
return TryAcceptHost(clientId)
? WaitForClientResult::Accept
: WaitForClientResult::Reject;
}
if (remoting::IsRendererChannel(availableChannels) && !Helpers::CanAdmitRenderer())
{
return WaitForClientResult::Reject;
}
return Base::OnRemoteClientConnected(clientId, availableChannels);
}
public:
template<typename... TArgs>
RemoteViewModelChannelServer(
Ptr<glr::json::Parser> parser,
bool _acceptRenderer,
TArgs&&... args
)
: Base(parser, _acceptRenderer, std::forward<TArgs>(args)...)
, Helpers(parser)
{
}
void Start() override
{
Base::Start();
}
vint Connect(const collections::List<WString>& requiredServiceNames)
{
Helpers::Start(this);
return Helpers::Connect(requiredServiceNames);
}
remoting::RpcDispatcherClient* GetDispatcher()
{
return Helpers::GetDispatcher();
}
Ptr<IDescriptable> RequestService(const WString& typeName)
{
return Helpers::RequestService(typeName);
}
bool CanAdmitRenderer()
{
return Helpers::CanAdmitRenderer();
}
void Stop() override
{
Helpers::Stop(Func<void()>([this]()
{
Base::Stop();
}));
}
void OnClientDisconnected(vint clientId) override
{
Base::OnClientDisconnected(clientId);
Helpers::OnClientDisconnected(clientId);
}
};
template<typename TServerBase, typename TRvmChannelServer>
class RemoteViewModelRendererChannelServer
: public remoting::RemotingChannelServer<TServerBase>
{
using Base = remoting::RemotingChannelServer<TServerBase>;
private:
TRvmChannelServer* rvmChannelServer = nullptr;
protected:
inter_process::WaitForClientResult OnRemoteClientConnected(
vint clientId,
const remoting::JsonChannelClient::ChannelNameList& availableChannels
) override
{
if (remoting::IsRendererChannel(availableChannels) && (!rvmChannelServer || !rvmChannelServer->CanAdmitRenderer()))
{
return inter_process::WaitForClientResult::Reject;
}
return Base::OnRemoteClientConnected(clientId, availableChannels);
}
public:
template<typename... TArgs>
RemoteViewModelRendererChannelServer(
Ptr<glr::json::Parser> parser,
TArgs&&... args
)
: Base(parser, true, std::forward<TArgs>(args)...)
{
}
void SetRvmChannelServer(TRvmChannelServer* value)
{
rvmChannelServer = value;
}
};
}
#endif