/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuNetSocketOverlappedOperation.Unix.cpp Date: 2022-8-26 Author: Reece ***/ #include "Networking.hpp" #include "AuNetSocketOverlappedOperation.hpp" #include #include "AuNetSocket.Unix.hpp" #include "AuNetError.hpp" namespace Aurora::IO::Net { SocketOverlappedOperation::SocketOverlappedOperation(bool bMultipleTrigger) : bMultipleTrigger(bMultipleTrigger) { this->pEvent = AuLoop::NewLSEvent(false, true); if (!this->pEvent) { return; } } SocketOverlappedOperation::SocketOverlappedOperation(const AuSPtr &pTrigger) { this->pEvent = pTrigger; } bool SocketOverlappedOperation::FinishOperation(const AuSPtr &pThat, const AuSPtr &pWorker, bool bReturnCode) { return this->FinishOperationEx(pThat, pWorker, bReturnCode, errno); } bool SocketOverlappedOperation::FinishOperationEx(const AuSPtr &pThat, const AuSPtr &pWorker, bool bReturnCode, AuUInt32 dwErrorCode) { if (bReturnCode) { this->OnIOComplete(); return true; } else { if ((dwErrorCode == EAGAIN) || (dwErrorCode == EINPROGRESS)) { return this->BeginOperation(pThat, pWorker); } else { // ERROR SysPushErrorIO("Couldn't connect [overlapped] (0x{:x})", dwErrorCode); this->uOsError = dwErrorCode; return false; } } } bool SocketOverlappedOperation::BeginOperation(const AuSPtr &that, const AuSPtr &pWorker) { this->pSocket = that; auto bStatus = pWorker->ToProcessor()->StartSimpleLSWatchEx(this->pEvent, AuSPtr(that, this), true); if (!bStatus) { this->pSocket.reset(); return false; } return true; } void SocketOverlappedOperation::UpdateTrigger(const AuSPtr &pTrigger) { this->pEvent = pTrigger; } bool SocketOverlappedOperation::IsValid() { return bool(this->pEvent); } void SocketOverlappedOperation::OnIOTick() { if (!this->bMultipleTrigger) { return; } AuLogDbg("On tick"); auto pTemp = AuExchange(this->pSocket, {}); if (this->HasFailed()) { this->OnOverlappedFailure(this->ToError()); } else { this->OnOverlappedComplete(); } } void SocketOverlappedOperation::OnIOComplete() { if (this->bMultipleTrigger) { return; } if (AuExchange(this->bHasFlipped, true)) { return; } if (this->HasFailed()) { this->OnOverlappedFailure(this->ToError()); } else { this->OnOverlappedComplete(); } this->pSocket.reset(); } void SocketOverlappedOperation::OnIOFailure() { if (AuExchange(this->bHasFlipped, true)) { return; } this->OnOverlappedFailure(this->ToError()); this->pSocket.reset(); } bool SocketOverlappedOperation::HasFailed() { return this->ToOsError() != 0; } AuUInt SocketOverlappedOperation::ToOsError() { if (this->uOsError) { return this->uOsError; } return this->uOsError; } bool SocketOverlappedOperation::HasComplete() { if (this->HasFailed()) { return false; } return this->ToOsError() == 0; } NetError SocketOverlappedOperation::ToError() { NetError error; NetError_SetOsError(error, this->ToOsError()); return error; } }