2022-07-02 22:08:52 +00:00
|
|
|
/***
|
|
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
|
|
|
|
File: AuRPCClientChannel.cpp
|
|
|
|
Date: 2022-6-29
|
|
|
|
Author: Reece
|
|
|
|
***/
|
|
|
|
#include <AuroraRuntime.hpp>
|
|
|
|
#include "AuRPC.hpp"
|
|
|
|
#include "AuRPCClientChannel.hpp"
|
|
|
|
#include "AuRPCRequest.hpp"
|
|
|
|
#include "AuRPCPipePacket.hpp"
|
|
|
|
|
2023-12-16 18:16:32 +00:00
|
|
|
AuRPCClientChannel::AuRPCClientChannel(AuSPtr<AuRPC> parent) :
|
|
|
|
parent_(parent),
|
|
|
|
pipe_(this)
|
|
|
|
{ }
|
|
|
|
|
2022-07-02 22:08:52 +00:00
|
|
|
bool AuRPCClientChannel::OnConnect()
|
|
|
|
{
|
|
|
|
auto request = AuMakeShared<AuRPCRequest>();
|
|
|
|
request->WriteHeaderConnect();
|
|
|
|
AuRPCPipePacket packet;
|
|
|
|
packet.clientRequest = request;
|
|
|
|
packet.protPacket = true;
|
|
|
|
packet.clientChannel = SharedFromThis();
|
|
|
|
this->pipe_.SendPacket(packet);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::Disconnect()
|
|
|
|
{
|
|
|
|
this->pipe_.Deinit();
|
|
|
|
Finalize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::SendRequest(AuSPtr<AuIRPCRequest> response2)
|
|
|
|
{
|
|
|
|
auto response = AuStaticCast<AuRPCRequest>(response2);
|
|
|
|
if (!response)
|
|
|
|
{
|
|
|
|
SysPushErrorArg();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
RpcLogDebug("Client sending request of bytes: {}", response->GetData().length);
|
|
|
|
|
|
|
|
AuRPCPipePacket packet;
|
|
|
|
packet.clientRequest = response;
|
|
|
|
packet.clientChannel = SharedFromThis();
|
|
|
|
this->pipe_.SendPacket(packet);
|
|
|
|
}
|
|
|
|
|
2023-12-16 18:16:32 +00:00
|
|
|
AuUInt64 AuRPCClientChannel::GetConnectTimeNS()
|
|
|
|
{
|
|
|
|
return this->uConnectTime_;
|
|
|
|
}
|
|
|
|
|
2023-12-16 22:15:23 +00:00
|
|
|
bool AuRPCClientChannel::SendMessage(const AuMemoryViewRead &view, bool bLarge)
|
2023-12-16 18:16:32 +00:00
|
|
|
{
|
2023-12-16 22:15:23 +00:00
|
|
|
if (!bLarge &&
|
|
|
|
view.length < this->parent_->GetLargePacketLength())
|
|
|
|
{
|
|
|
|
auto pMessage = AuMakeShared<AuRPCRequest>();
|
|
|
|
if (!pMessage)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
pMessage->dataType = kGeneralServerMessage;
|
|
|
|
pMessage->SetData(view);
|
|
|
|
this->SendRequest(pMessage);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
auto pSharedMemory = AuIPC::NewSharedMemory(view.length);
|
|
|
|
if (!pSharedMemory)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto dest = pSharedMemory->GetMemory();
|
|
|
|
AuMemcpy(dest.ptr, view.ptr, view.length);
|
|
|
|
|
|
|
|
auto pMessage = AuMakeShared<AuRPCRequest>();
|
|
|
|
if (!pMessage)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
pMessage->dataType = kGeneralMassiveMessage;
|
|
|
|
AuByteBuffer data;
|
|
|
|
data.Write(pSharedMemory->ExportToString());
|
|
|
|
if (!data)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
pMessage->SetData(data);
|
|
|
|
this->SendRequest(pMessage);
|
|
|
|
return true;
|
|
|
|
}
|
2023-12-16 18:16:32 +00:00
|
|
|
}
|
|
|
|
|
2022-07-02 22:08:52 +00:00
|
|
|
AuSPtr<AuRPC> AuRPCClientChannel::ToContext()
|
|
|
|
{
|
|
|
|
return this->parent_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::OnDisconnect(bool error)
|
|
|
|
{
|
|
|
|
RpcLogDebug("AuRPCClientChannel::OnDisconnect");
|
2022-07-08 03:30:03 +00:00
|
|
|
|
|
|
|
if (this->bConnected_ || !this->bConnectingAlternate_)
|
|
|
|
{
|
|
|
|
Finalize();
|
|
|
|
}
|
2022-07-02 22:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool AuRPCClientChannel::OnDataAvailable(AuByteBuffer &view)
|
|
|
|
{
|
|
|
|
RpcLogDebug("AuRPCClientChannel::OnDataAvailable");
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
auto bytesAvailable = view.RemainingBytes();
|
|
|
|
|
|
|
|
if (bytesAvailable < 4)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto oldRead = view.readPtr;
|
2022-07-07 04:16:27 +00:00
|
|
|
auto frameLength = view.Read<AuUInt32>();
|
2022-07-02 22:08:52 +00:00
|
|
|
|
2022-07-07 04:16:27 +00:00
|
|
|
if (!frameLength)
|
|
|
|
{
|
|
|
|
Disconnect();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frameLength > bytesAvailable)
|
2022-07-02 22:08:52 +00:00
|
|
|
{
|
|
|
|
view.readPtr = oldRead;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-07-07 04:16:27 +00:00
|
|
|
auto endPtr = oldRead + frameLength;
|
|
|
|
|
2022-07-02 22:08:52 +00:00
|
|
|
auto packetType = view.Read<AuUInt8>();
|
|
|
|
|
|
|
|
if (packetType == kResponseConnectOK)
|
|
|
|
{
|
|
|
|
this->bConnected_ = true;
|
|
|
|
this->ProcessConnectionOK();
|
|
|
|
}
|
|
|
|
else if (packetType == kResponseMulticonnect)
|
|
|
|
{
|
|
|
|
this->bConnectingAlternate_ = true;
|
2022-07-08 03:30:03 +00:00
|
|
|
this->pipe_.Deinit();
|
2022-07-02 22:08:52 +00:00
|
|
|
this->Init(view.Read<AuString>());
|
|
|
|
}
|
|
|
|
else if (packetType == kResponseRPC)
|
|
|
|
{
|
|
|
|
auto response = AuMakeShared<AuRPCResponse>();
|
|
|
|
if (!response)
|
|
|
|
{
|
|
|
|
SysPushErrorMem();
|
|
|
|
view.readPtr = oldRead;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-07-07 04:16:27 +00:00
|
|
|
auto oldLength = view.length;
|
2023-12-16 18:16:32 +00:00
|
|
|
auto oldWriteHead = view.writePtr;
|
2022-07-07 04:16:27 +00:00
|
|
|
view.length = (oldRead - view.base) + frameLength;
|
2023-12-16 18:16:32 +00:00
|
|
|
view.writePtr = view.base + view.length;
|
2022-07-02 22:08:52 +00:00
|
|
|
response->message = &view;
|
|
|
|
|
|
|
|
response->Deserialize();
|
|
|
|
this->ProcessResponse(response);
|
2022-07-07 04:16:27 +00:00
|
|
|
|
|
|
|
view.readPtr = endPtr;
|
2023-12-16 18:16:32 +00:00
|
|
|
view.writePtr = oldWriteHead;
|
|
|
|
view.length = oldLength;
|
|
|
|
}
|
|
|
|
else if (packetType == kGeneralBroadcast ||
|
|
|
|
packetType == kGeneralClientMessage)
|
|
|
|
{
|
|
|
|
auto oldLength = view.length;
|
|
|
|
auto oldWriteHead = view.writePtr;
|
|
|
|
view.length = (oldRead - view.base) + frameLength;
|
|
|
|
view.writePtr = view.base + view.length;
|
|
|
|
|
|
|
|
if (auto pCallbacks = this->callbacks_)
|
|
|
|
{
|
|
|
|
if (packetType == kGeneralBroadcast)
|
|
|
|
{
|
|
|
|
pCallbacks->OnBroadcast(view);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2023-12-16 22:15:23 +00:00
|
|
|
pCallbacks->OnMessage(view);
|
2023-12-16 18:16:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
view.readPtr = endPtr;
|
|
|
|
view.writePtr = oldWriteHead;
|
2022-07-07 04:16:27 +00:00
|
|
|
view.length = oldLength;
|
2022-07-02 22:08:52 +00:00
|
|
|
}
|
2023-12-16 22:15:23 +00:00
|
|
|
else if (packetType == kGeneralMassiveMessage)
|
|
|
|
{
|
|
|
|
auto oldLength = view.length;
|
|
|
|
auto oldWriteHead = view.writePtr;
|
|
|
|
view.length = (oldRead - view.base) + frameLength;
|
|
|
|
view.writePtr = view.base + view.length;
|
2022-07-02 22:08:52 +00:00
|
|
|
|
2023-12-16 22:15:23 +00:00
|
|
|
auto str = view.Read<AuString>();
|
|
|
|
if (view)
|
|
|
|
{
|
|
|
|
auto pMemory = AuIPC::ImportSharedMemory(str);
|
|
|
|
if (!pMemory)
|
|
|
|
{
|
|
|
|
SysPushErrorIO("Couldnt open shared memory for large packet");
|
|
|
|
this->FatalIOError();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
AuByteBuffer buf(pMemory->GetMemory());
|
|
|
|
if (!buf)
|
|
|
|
{
|
|
|
|
SysPushErrorMemory();
|
|
|
|
this->FatalIOError();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auto pCallbacks = this->callbacks_)
|
|
|
|
{
|
|
|
|
pCallbacks->OnMessage(buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
view.readPtr = oldRead + frameLength;
|
|
|
|
view.writePtr = oldWriteHead;
|
|
|
|
view.length = oldLength;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
while (true);
|
2022-07-02 22:08:52 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AuRPCClientChannel::Init(const AuString &ipc)
|
|
|
|
{
|
|
|
|
return this->pipe_.Init(ipc);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::FatalIOError()
|
|
|
|
{
|
|
|
|
RpcLogDebug("AuRPCClientChannel::FatalIOError");
|
|
|
|
Disconnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::ProcessConnectionOK()
|
|
|
|
{
|
2023-12-16 18:16:32 +00:00
|
|
|
this->uConnectTime_ = AuTime::SteadyClockNS();
|
|
|
|
|
2022-07-02 22:08:52 +00:00
|
|
|
auto re = AuExchange(this->outstandingRequests, AuList<AuSPtr<AuRPCRequest>>{});
|
|
|
|
|
|
|
|
if (this->callbacks_)
|
|
|
|
{
|
|
|
|
this->callbacks_->OnConnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto a : re)
|
|
|
|
{
|
|
|
|
this->SendRequest(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::ProcessResponse(const AuSPtr<AuRPCResponse> &response)
|
|
|
|
{
|
|
|
|
RpcLogDebug("AuRPCClientChannel::ProcessResponse");
|
|
|
|
|
|
|
|
for (auto itr = this->outstandingRequests.begin();
|
|
|
|
itr != this->outstandingRequests.end();
|
2022-07-09 00:49:36 +00:00
|
|
|
itr++)
|
2022-07-02 22:08:52 +00:00
|
|
|
{
|
|
|
|
if (response->cookie != AuUInt(itr->get()))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto req = *itr;
|
|
|
|
this->outstandingRequests.erase(itr);
|
|
|
|
|
|
|
|
if (req->callback)
|
|
|
|
{
|
|
|
|
req->callback->OnResponse(*response);
|
|
|
|
}
|
2022-07-09 00:49:36 +00:00
|
|
|
break;
|
2022-07-02 22:08:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AuRPCClientChannel::IsConnected()
|
|
|
|
{
|
|
|
|
return this->bConnected_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::SetCallbacks(const AuSPtr<AuIRPCChannelCallbacks> &callbacks)
|
|
|
|
{
|
|
|
|
if (!callbacks)
|
|
|
|
{
|
|
|
|
SysPushErrorArg();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsConnected())
|
|
|
|
{
|
|
|
|
callbacks->OnConnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
this->callbacks_ = callbacks;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AuRPCClientChannel::Finalize()
|
|
|
|
{
|
|
|
|
auto re = AuExchange(this->outstandingRequests, AuList<AuSPtr<AuRPCRequest>>{});
|
|
|
|
|
2022-07-05 20:16:22 +00:00
|
|
|
if (AuExchange(this->bIsDead_, true))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-02 22:08:52 +00:00
|
|
|
for (auto a : re)
|
|
|
|
{
|
|
|
|
a->callback->OnResponse(AuRPCResponse(ERPCError::eAborted));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this->callbacks_)
|
|
|
|
{
|
|
|
|
this->callbacks_->OnDisconnect();
|
2022-07-08 03:30:03 +00:00
|
|
|
this->callbacks_.reset();
|
2022-07-02 22:08:52 +00:00
|
|
|
}
|
|
|
|
}
|