/*** 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" 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(this->pParent_->ToPlatformHandle(), -1); if (!pWaitHandle) { return false; } this->pWatch_ = this->pParent_->ToWorker()->ToProcessor()->StartSimpleLSWatchEx(pWaitHandle, AuSPtr(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; } // Create socket this->nextSocketPtr = AuMakeShared(this->pInterface_, this->pParent_->ToWorkerEx(), pNewDriver, (AuUInt)this->nextSocket); if (!bool(this->nextSocketPtr)) { // TODO: schedule retry SysPushErrorNet("Couldn't allocate a socket"); ::close(this->nextSocket); return false; } // Preinit if (!nextSocketPtr->SendPreestablish()) { SysPushErrorNet("Couldn't preestablish next socket"); 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(); // 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; } }