mirror of
https://github.com/vczh-libraries/Release.git
synced 2026-10-01 18:22:58 +08:00
521 lines
15 KiB
C++
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
|
|
|