AuroraRPC/Source/AuRPCServer.cpp

134 lines
2.8 KiB
C++
Raw Normal View History

2022-07-02 22:08:52 +00:00
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuRPCServer.cpp
Date: 2022-6-29
Author: Reece
***/
#include <AuroraRuntime.hpp>
#include "AuRPC.hpp"
#include "AuRPCServer.hpp"
#include "AuRPCServerChannel.hpp"
#include "AuRPCRequest.hpp"
bool AuRPCServer::Init(AuRPC *parent, AuAsync::WorkerPId_t worker)
{
if (this->channel)
{
SysPushErrorGen("Double init");
return {};
}
this->lock = AuThreadPrimitives::RWLockUnique();
if (!this->lock)
{
SysPushErrorMem();
return {};
}
this->worker = worker;
this->parent = parent;
this->channel = NewChannel();
if (!this->channel)
{
return false;
}
this->channel->MakeTemp();
return true;
}
bool AuRPCServer::RegisterService(const AuSPtr<AuIRPCService> service)
{
if (!service)
{
SysPushErrorArg();
return {};
}
AU_LOCK_GUARD(this->lock->AsWritable());
return AuTryInsert(this->serviceTable, service->GetId(), service);
}
AuString AuRPCServer::ExportString()
{
return ToPrimaryChannel()->ExportString();
}
AuSPtr<AuRPCServerChannel> AuRPCServer::ToPrimaryChannel()
{
if (this->channel)
{
return this->channel;
}
return this->channel = NewChannel();
}
void AuRPCServer::Dispatch(AuRPCServerChannel *channel,
const AuSPtr<AuRPCRequest> &request,
AuByteBuffer *buffer)
{
AU_LOCK_GUARD(this->lock->AsReadable());
auto response = AuMakeShared<AuRPCResponseOwned>();
SysAssert(response);
response->cookie = request->cookie;
response->PrepareResponse(kResponseRPC);
auto itr = this->serviceTable.find(request->serviceId);
if (itr == this->serviceTable.end())
{
response->FinalizeWrite();
channel->SendResponse(response);
return;
}
try
{
response->PrepareMessage();
itr->second->Dispatch(*response, request->methodId, *buffer);
channel->SendResponse(response);
response->FinalizeWrite();
}
catch (...)
{
SysPushErrorCatch();
channel->FatalError();
}
}
AuSPtr<AuRPCServerChannel> AuRPCServer::NewChannel()
{
auto eh = AuMakeShared<AuRPCServerChannel>(this->parent->SharedFromThis(), AuSPtr<AuRPCServer>(this->parent->SharedFromThis(), this));
if (!eh)
{
return {};
}
if ((this->worker.second != AuAsync::kThreadIdAny) &&
(this->worker == AuAsync::GetCurrentWorkerPId()))
{
if (!eh->Init())
{
return {};
}
}
else
{
AuAsync::NewWorkItem(this->worker, AuMakeShared<AuAsync::BasicWorkStdFunc>([&]()
{
if (!eh->Init())
{
eh.reset();
}
}), true)->Dispatch()->BlockUntilComplete();
}
return eh;
}