AuroraRuntime/Source/IO/Net/AuNetSocketServerAcceptReadOperation.Unix.cpp
J Reece Wilson 766be57a46 [+] Linux build [again]
[+] ProcessSectionViewReserved.Unix.cpp
[*] Fix missing ::Flush() member on ViewWriter
2022-12-16 00:41:01 +00:00

183 lines
5.9 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuNetSocketServerAcceptReadOperation.NT.cpp
Date: 2022-8-22
Author: Reece
***/
#include "Networking.hpp"
#include "AuNetSocketServer.hpp"
#include "AuNetSocket.hpp"
#include "AuNetEndpoint.hpp"
#include "AuNetInterface.hpp"
#include "AuNetWorker.hpp"
#include "AuNetEndpoint.hpp"
namespace Aurora::IO::Net
{
SocketServerAcceptReadOperation::SocketServerAcceptReadOperation(NetInterface *pInterface,
SocketServer *pParent) :
pInterface_(pInterface),
SocketServerAcceptReadOperationBase(pParent)
{
}
void SocketServerAcceptReadOperation::Destroy()
{
if (this->pWatch_)
{
this->pWatch_->StopWatch();
}
}
bool SocketServerAcceptReadOperation::DoTick()
{
this->Pretick(); // TODO: send soft error
return true;
}
bool SocketServerAcceptReadOperation::InitOnce()
{
auto pWaitHandle = AuMakeShared<Loop::LSHandle>(this->pParent_->ToPlatformHandle(), -1);
if (!pWaitHandle)
{
return false;
}
this->pWatch_ = this->pParent_->ToWorker()->ToProcessor()->StartSimpleLSWatchEx(pWaitHandle,
AuSPtr<IIOSimpleEventListener>(this->pParent_->SharedFromThis(), this),
false);
return bool(this->pWatch_);
}
bool SocketServerAcceptReadOperation::Pretick()
{
auto &localAddress = this->pParent_->GetLocalEndpoint();
char addressRemote[64];
socklen_t addressLength { this->pParent_->endpointSize_ };
this->nextSocket =
::accept(this->pParent_->ToPlatformHandle(),
(sockaddr *)addressRemote,
&addressLength);
if (this->nextSocket == -1)
{
return false;
}
// Yoink factory and create driver
auto pFactory = this->pParent_->GetFactory();
if (!bool(pFactory))
{
SysPushErrorNet("Socket missing factory");
return false;
}
auto pNewDriver = pFactory->NewSocketDriver();
if (!bool(pNewDriver))
{
SysPushErrorNet("Socket factory failed to provide a new instance ahead of server acceptance");
return false;
}
NetWorker *pWorker;
if (this->pParent_->bMultiThreaded)
{
pWorker = this->pInterface_->TryScheduleEx().get();
}
else
{
pWorker = this->pParent_->ToWorkerEx();
}
// Create socket
this->nextSocketPtr = AuMakeShared<Socket>(this->pInterface_,
pWorker,
pNewDriver,
(AuUInt)this->nextSocket);
if (!bool(this->nextSocketPtr))
{
// TODO: schedule retry
SysPushErrorNet("Couldn't allocate a socket");
::close(this->nextSocket);
return false;
}
// brrrrrrrrrr
AuMemcpy(this->nextSocketPtr->remoteEndpoint_.hint, addressRemote, addressLength);
this->nextSocketPtr->UpdateLocalEndpoint();
this->nextSocketPtr->remoteEndpoint_.transportProtocol = this->nextSocketPtr->localEndpoint_.transportProtocol = this->pParent_->localEndpoint_.transportProtocol;
// Deoptimize (sockaddr -> binary) endpoints
UpdateNextSocketAddresses();
if (this->pParent_->bMultiThreaded)
{
auto pCallback = AuMakeShared<IIOProcessorWorkUnitFunctional>([=]()
{
// Preinit
if (!nextSocketPtr->SendPreestablish())
{
SysPushErrorNet("Couldn't establish TCP socket on alternative thread");
nextSocketPtr->CloseSocket();
return;
}
// Start the channels
this->nextSocketPtr->DoMain();
},
[]()
{
});
if (!pCallback)
{
SysPushErrorMemory();
SysPushErrorNet("Memory");
return false;
}
if (!pWorker->ToProcessor()->SubmitIOWorkItem(pCallback))
{
SysPushErrorMemory();
SysPushErrorNet("couldnt schedule accept on thread");
return false;
}
}
else
{
// Preinit
if (!nextSocketPtr->SendPreestablish())
{
SysPushErrorNet("Couldn't preestablish next socket");
return false;
}
// Start the channels
this->nextSocketPtr->DoMain();
}
// And we don't need this reference anymore...
this->nextSocketPtr.reset();
return true;
}
void SocketServerAcceptReadOperation::UpdateNextSocketAddresses()
{
SysAssert(this->nextSocketPtr);
#if 0
this->nextSocketPtr->endpointSize_ = this->pParent_->endpointSize_;
AuMemcpy(this->nextSocketPtr->localEndpoint_.hint, &this->addresses_[0], this->pParent_->endpointSize_);
AuMemcpy(this->nextSocketPtr->remoteEndpoint_.hint, &this->addresses_[16 + this->pParent_->endpointSize_], this->pParent_->endpointSize_);
#endif
DeoptimizeEndpoint(nextSocketPtr->remoteEndpoint_);
DeoptimizeEndpoint(nextSocketPtr->localEndpoint_);
nextSocketPtr->remoteEndpoint_.transportProtocol = nextSocketPtr->localEndpoint_.transportProtocol = this->pParent_->GetLocalEndpoint().transportProtocol;
}
}