AuroraRuntime/Source/IO/Net/AuNetResolver.NT.cpp
2022-12-14 01:35:18 +00:00

205 lines
5.1 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuNetResolver.NT.cpp
Date: 2022-8-17
Author: Reece
***/
#include "Networking.hpp"
#include "AuNetResolver.NT.hpp"
#include "AuNetEndpoint.hpp"
namespace Aurora::IO::Net
{
NetResolver::NetResolver(const AuSPtr<INetWorker> &pWorker) :
pWorker_(pWorker)
{
}
NetResolver::NetResolver(const AuSPtr<INetWorker> &pWorker,
const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &pCompletion) :
pCompletion_(pCompletion),
pWorker_(pWorker)
{
}
NetResolver::~NetResolver()
{
}
bool NetResolver::Start()
{
ADDRINFOEXW infoEx { 0 };
int iInfoEx { 0 };
if (this->bA && !this->bAAAA)
{
infoEx.ai_family = AF_INET;
}
else if (this->bAAAA)
{
infoEx.ai_family = AF_INET6;
//infoEx.ai_flags = AI_V4MAPPED; // beats returning nothing...
}
else if (this->bA && this->bAAAA)
{
infoEx.ai_family = AF_UNSPEC;
//infoEx.ai_flags = AI_ALL;
}
else
{
return false;
}
int iRet {};
HANDLE hHandle = NULL;
if (GetAddrInfoExCancel_f)
{
iRet = GetAddrInfoExW(AuLocale::ConvertFromUTF8(this->hostname).data(),
nullptr,
NS_DNS,
nullptr,
&infoEx,
&this->resultHandle_,
nullptr,
&this->overlapped,
NULL,
&hHandle);
}
else
{
iRet = GetAddrInfoExW(AuLocale::ConvertFromUTF8(this->hostname).data(),
nullptr,
NS_DNS,
nullptr,
&infoEx,
&this->resultHandle_,
nullptr,
nullptr,
nullptr,
nullptr);
}
this->hName_ = hHandle;
return this->FinishOperationEx(AuSharedFromThis(),
this->pWorker_,
iRet == 0,
iRet);
}
void NetResolver::SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback)
{
this->pCompletion_ = callback;
}
void NetResolver::OnOverlappedComplete()
{
if (AuExchange(this->bHasCompleted_, true))
{
return;
}
if (this->Unpack())
{
if (this->pCompletion_)
{
try
{
this->pCompletion_->OnSuccess((void *)&this->processedIps_);
}
catch (...)
{
SysPushErrorCatch();
}
}
}
else
{
if (this->pCompletion_)
{
try
{
this->error_ = ENetworkError::eAsyncError;
this->pCompletion_->OnFailure((void *)&this->error_);
}
catch (...)
{
SysPushErrorCatch();
}
}
}
}
void NetResolver::OnOverlappedFailure(const NetError &error)
{
this->error_ = error;
if (this->pCompletion_)
{
try
{
this->pCompletion_->OnFailure((void *)&this->error_);
}
catch (...)
{
SysPushErrorCatch();
}
}
this->bHasCompleted_ = true;
}
bool NetResolver::HasFinished()
{
return this->bHasCompleted_;
}
void NetResolver::Cancel()
{
auto hHandle = AuExchange(this->hName_, (HANDLE)NULL);
if (hHandle != NULL)
{
if (GetAddrInfoExCancel_f)
{
GetAddrInfoExCancel_f(&hHandle);
}
}
while (!this->HasComplete())
{
IOYield();
}
}
const NetError &NetResolver::GetError()
{
return this->error_;
}
bool NetResolver::Unpack()
{
auto pCurrent = this->resultHandle_;
while (pCurrent)
{
NetEndpoint endpoint;
AuMemcpy(endpoint.hint, pCurrent->ai_addr, pCurrent->ai_addrlen);
DeoptimizeEndpoint(endpoint);
if (!AuTryInsert(this->processedIps_, endpoint.ip))
{
return false;
}
pCurrent = pCurrent->ai_next;
}
if (this->resultHandle_)
{
::FreeAddrInfoExW(this->resultHandle_);
}
return true;
}
}