134 lines
2.8 KiB
C++
134 lines
2.8 KiB
C++
|
/***
|
||
|
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;
|
||
|
}
|