AuroraRPC/Source/AuRPCServerChannel.cpp
Reece Wilson 14ebab9d22 [+] AuIRPCRequest::EmptyRequest()
[*] De boog numero 2
> Constrain dispatch bytebuffer views to the exact frame length
2022-07-07 05:16:27 +01:00

183 lines
3.7 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuRPCServerChannel.cpp
Date: 2022-6-29
Author: Reece
***/
#include <AuroraRuntime.hpp>
#include "AuRPC.hpp"
#include "AuRPCServerChannel.hpp"
#include "AuRPCRequest.hpp"
#include "AuRPCPipePacket.hpp"
AuRPCServerChannel::AuRPCServerChannel(AuSPtr<AuRPC> parent, AuSPtr<AuRPCServer> server) :
parent(parent),
pipe(this),
server_(server)
{
}
AuSPtr<AuRPC> AuRPCServerChannel::ToContext()
{
return this->parent;
}
void AuRPCServerChannel::SendResponse(AuSPtr<AuRPCResponse> response)
{
if (response->message->flagWriteError)
{
this->FatalError();
return;
}
AuRPCPipePacket packet;
packet.serverResponse = response;
this->pipe.SendPacket(packet);
}
AuString AuRPCServerChannel::ExportString()
{
return this->pipe.pipe->ExportToString();
}
bool AuRPCServerChannel::OnConnect()
{
RpcLogDebug("Server channel: on connect");
return true;
}
void AuRPCServerChannel::OnDisconnect(bool error)
{
RpcLogDebug("Server channel disconnected: {}", error);
}
bool AuRPCServerChannel::OnDataAvailable(AuByteBuffer& view)
{
do
{
auto bytesAvailable = view.RemainingBytes();
if (bytesAvailable < 4)
{
return true;
}
auto oldRead = view.readPtr;
auto frameLength = view.Read<AuUInt32>();
if (!frameLength)
{
FatalError();
return false;
}
if (frameLength > bytesAvailable)
{
view.readPtr = oldRead;
return true;
}
auto packetType = view.Read<AuUInt8>();
if (packetType == kRequestConnect)
{
if (this->isTempChannel_)
{
this->SendToNewChannel();
}
else
{
this->SendConnectOK();
}
}
else if (packetType == kRequestRPC)
{
auto request = AuMakeShared<AuRPCRequest>();
if (!request)
{
SysPushErrorMem();
view.readPtr = oldRead;
return true;
}
request->serviceId = view.Read<AuUInt32>();
request->methodId = view.Read<AuUInt32>();
request->cookie = view.Read<AuUInt64>();
auto oldLength = view.length;
view.length = (oldRead - view.base) + frameLength;
this->server_->Dispatch(this, request, &view);
view.readPtr = frameLength + oldRead;
view.length = oldLength;
}
}
while (true);
return true;
}
void AuRPCServerChannel::SendConnectOK()
{
RpcLogDebug("AuRPCServerChannel::SendConnectOK");
auto res = AuMakeShared<AuRPCResponseOwned>();
if (!res)
{
FatalError();
return;
}
res->PrepareResponse(kResponseConnectOK);
res->FinalizeWrite();
this->SendResponse(res);
}
void AuRPCServerChannel::SendToNewChannel()
{
RpcLogDebug("AuRPCServerChannel::SendToNewChannel");
auto res = AuMakeShared<AuRPCResponseOwned>();
if (!res)
{
FatalError();
return;
}
res->PrepareResponse(kResponseMulticonnect);
auto channel = this->server_->NewChannel();
if (!channel)
{
this->FatalError();
return;
}
if (!AuTryInsert(this->subchannels_, channel))
{
this->FatalError();
return;
}
res->buffer->Write(channel->ExportString());
res->FinalizeWrite();
this->SendResponse(res);
}
void AuRPCServerChannel::FatalError()
{
RpcLogDebug("AuRPCServerChannel::FatalError");
this->pipe.Deinit();
}
bool AuRPCServerChannel::Init()
{
return this->pipe.Init();
}