[+] Added basic posix name resolution for when glibc isnt present or when being built on non-glibc toolchains

This commit is contained in:
Reece Wilson 2024-07-01 12:23:18 +01:00
parent 592afe00a7
commit e7597b8463
4 changed files with 187 additions and 21 deletions

View File

@ -42,6 +42,10 @@ namespace Aurora
{
p__cxa_throw = (decltype(p__cxa_throw))dlsym(RTLD_DEFAULT, "__cxa_throw");
}
pgai_error = (decltype(pgai_error))dlsym(RTLD_DEFAULT, "gai_error");
pgai_cancel = (decltype(pgai_cancel))dlsym(RTLD_DEFAULT, "gai_cancel");
pgetaddrinfo_a = (decltype(pgetaddrinfo_a))dlsym(RTLD_DEFAULT, "getaddrinfo_a");
#endif
}

View File

@ -11,6 +11,7 @@
#include <sys/socket.h>
struct robust_list_head;
struct glibc_aicb;
namespace Aurora
{
@ -68,4 +69,9 @@ namespace Aurora
inline void (AU_NORETURN *p__cxa_throw)(void *pException, std::type_info *typeInfo, void (*fDtor)(void *pThis));
inline AuUInt32 (*p_Unwind_RaiseException)(void *pException);
inline int (* pgai_error) (struct glibc_aicb *pContext);
inline int (* pgai_cancel) (struct glibc_aicb *pContext);
inline int (* pgetaddrinfo_a) (int mode, struct glibc_aicb **pContext, int count, struct sigevent *sig);
#define AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS
}

View File

@ -119,6 +119,8 @@ namespace Aurora::IO::Net
{
int iInfoEx { 0 };
AuMemset(&this->infoEx, 0, sizeof(infoEx));
if (this->bA && this->bAAAA)
{
infoEx.ai_family = AF_UNSPEC;
@ -136,6 +138,14 @@ namespace Aurora::IO::Net
return false;
}
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
if (!pgetaddrinfo_a)
{
return this->StartStandard();
}
sigevent event {0};
event.sigev_notify = SIGEV_SIGNAL;
event.sigev_signo = GetGAIAsyncIOSignal();
@ -160,28 +170,38 @@ namespace Aurora::IO::Net
pBase->ar_request = (addrinfo *)&infoEx;
pBase->ar_name = hostname.c_str();
AuTryInsert(tlsResolvers, AuSharedFromThis());
if (!AuTryInsert(tlsResolvers, AuSharedFromThis()))
{
SysPushErrorMemory();
return false;
}
int iStatus = ::getaddrinfo_a(GAI_NOWAIT,
&pBase,
1,
&event);
int iStatus = pgetaddrinfo_a(GAI_NOWAIT,
&pBase,
1,
&event);
switch (iStatus)
{
case EAI_AGAIN:
{
SysPushErrorNet("Low Resources | Failed to resolve");
this->uOsError = iStatus;
this->error_ = this->ToError();
return false;
}
case EAI_MEMORY:
{
SysPushErrorNet("Out of Memory | Failed to resolve");
this->uOsError = iStatus;
this->error_ = this->ToError();
return false;
}
case EAI_SYSTEM:
{
SysPushErrorNet("Invalid | Failed to resolve");
SysPushErrorNet("Invalid | Failed to resolve: {}", errno);
this->uOsError = errno;
this->error_ = this->ToError();
return false;
}
}
@ -189,12 +209,87 @@ namespace Aurora::IO::Net
if (iStatus != 0)
{
SysPushErrorNet("{}", iStatus);
this->uOsError = iStatus;
this->error_ = this->ToError();
return false;
}
return this->BeginOperation(AuSharedFromThis(),
this->pWorker_);
#else
return this->StartStandard();
#endif
}
bool NetResolver::StartStandard()
{
auto pShared = this->SharedFromThis();
auto pThread = AuThreads::ThreadUnique(AuThreads::ThreadInfo(
AuMakeShared<AuThreads::IThreadVectorsFunctional>(AuThreads::IThreadVectorsFunctional::OnEntry_t(std::bind([=]()
{
int iRet {};
addrinfo infoA { 0 };
addrinfo *pInfoRet {};
infoA.ai_family = infoEx.ai_family;
iRet = getaddrinfo(pShared->hostname.c_str(),
nullptr,
&infoA,
&pInfoRet);
if (iRet == 0)
{
auto pCurrent = pInfoRet;
while (pCurrent)
{
NetEndpoint endpoint;
AuMemcpy(endpoint.hint, pCurrent->ai_addr, pCurrent->ai_addrlen);
DeoptimizeEndpoint(endpoint);
if (!AuTryInsert(pShared->processedIps_, endpoint.ip))
{
pShared->bForceError_ = true;
break;
}
pCurrent = pCurrent->ai_next;
}
}
else
{
pShared->bForceError_ = true;
pShared->uOsError = iRet;
pShared->error_ = pShared->ToError();
}
if (pInfoRet)
{
freeaddrinfo(pInfoRet);
}
pShared->pEvent->Set();
})),
AuThreads::IThreadVectorsFunctional::OnExit_t{}),
"Legacy Posix DNS Request"
));
if (!pThread)
{
return false;
}
pThread->Run();
pThread->Detach();
this->UpdateTrigger(pShared->pEvent);
return this->BeginOperation(AuSharedFromThis(),
this->pWorker_);
}
void NetResolver::SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback)
@ -282,28 +377,58 @@ namespace Aurora::IO::Net
bool NetResolver::CheckAsync()
{
int iStatus = ::gai_error(&this->gnuAsyncOperation);
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
if (!pgai_error)
{
return !this->bForceError_;
}
int iStatus = pgai_error(&this->gnuAsyncOperation);
return ((iStatus == 0) ||
(iStatus == EAI_CANCELED));
#else
return !this->bForceError_;
#endif
}
void NetResolver::Cancel()
{
while (!this->HasComplete())
{
int iStatus = ::gai_cancel(&this->gnuAsyncOperation);
switch (iStatus)
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
if (pgai_cancel)
{
case EAI_CANCELED:
case EAI_ALLDONE:
break;
case EAI_NOTCANCELED:
int iStatus = pgai_cancel(&this->gnuAsyncOperation);
switch (iStatus)
{
IOYield();
AuThreading::ContextYield();
continue;
case EAI_CANCELED:
case EAI_ALLDONE:
break;
case EAI_NOTCANCELED:
{
IOYield();
AuThreading::ContextYield();
continue;
}
}
}
else
{
IOYield();
AuThreading::ContextYield();
}
#else
IOYield();
AuThreading::ContextYield();
#endif
}
}
@ -334,11 +459,15 @@ namespace Aurora::IO::Net
{
return false;
}
freeaddrinfo(pItr);
}
return true;
}
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
static void Annoying(int)
{
for (const auto &gawad : tlsResolvers)
@ -350,15 +479,21 @@ namespace Aurora::IO::Net
}
}
#endif
void InitFreetardedResolver()
{
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
struct sigaction action =
{
.sa_handler = Annoying,
.sa_flags = SA_ONSTACK
.sa_flags = SA_ONSTACK | SA_RESTART
};
::sigemptyset(&action.sa_mask);
::sigaction(GetGAIAsyncIOSignal(), &action, nullptr);
#endif
}
}

View File

@ -10,6 +10,27 @@
#include "AuNetSocketOverlappedOperation.hpp"
#include "AuNetSocket.hpp"
#if !defined(EAI_AGAIN)
#define EAI_AGAIN -3
#endif
#if !defined(EAI_MEMORY)
#define EAI_MEMORY -10
#endif
#if !defined(EAI_SYSTEM)
#define EAI_SYSTEM -11
#endif
struct glibc_aicb
{
const char * ar_name { };
const char * ar_service { };
const struct addrinfo *ar_request { };
struct addrinfo * ar_result { };
int reserved[10] { };
};
namespace Aurora::IO::Net
{
struct Socket;
@ -30,6 +51,7 @@ namespace Aurora::IO::Net
AuString hostname;
bool Start();
bool StartStandard();
void SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback);
@ -52,10 +74,9 @@ namespace Aurora::IO::Net
bool bHasCompleted_ {};
bool bHasUnpackedEarly {};
NetError error_;
addrinfo infoEx { 0 };
gaicb gnuAsyncOperation {}; // freetarded
addrinfo infoEx { };
bool bForceError_ {};
glibc_aicb gnuAsyncOperation {}; // freetarded
bool CheckAsync();
friend struct ThreadLocalCaughtCompletion;
};