From e7597b8463440f2959b4c7c52dac5bc5177b6749 Mon Sep 17 00:00:00 2001 From: J Reece Wilson Date: Mon, 1 Jul 2024 12:23:18 +0100 Subject: [PATCH] [+] Added basic posix name resolution for when glibc isnt present or when being built on non-glibc toolchains --- Source/AuProcAddresses.Linux.cpp | 4 + Source/AuProcAddresses.Linux.hpp | 6 + Source/IO/Net/AuNetResolver.Unix.cpp | 169 ++++++++++++++++++++++++--- Source/IO/Net/AuNetResolver.Unix.hpp | 29 ++++- 4 files changed, 187 insertions(+), 21 deletions(-) diff --git a/Source/AuProcAddresses.Linux.cpp b/Source/AuProcAddresses.Linux.cpp index be234a4c..86b98ef7 100644 --- a/Source/AuProcAddresses.Linux.cpp +++ b/Source/AuProcAddresses.Linux.cpp @@ -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 } diff --git a/Source/AuProcAddresses.Linux.hpp b/Source/AuProcAddresses.Linux.hpp index b21eef8c..ec1c7e10 100644 --- a/Source/AuProcAddresses.Linux.hpp +++ b/Source/AuProcAddresses.Linux.hpp @@ -11,6 +11,7 @@ #include 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 } \ No newline at end of file diff --git a/Source/IO/Net/AuNetResolver.Unix.cpp b/Source/IO/Net/AuNetResolver.Unix.cpp index ecee9efa..0308249d 100644 --- a/Source/IO/Net/AuNetResolver.Unix.cpp +++ b/Source/IO/Net/AuNetResolver.Unix.cpp @@ -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::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, 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 } } \ No newline at end of file diff --git a/Source/IO/Net/AuNetResolver.Unix.hpp b/Source/IO/Net/AuNetResolver.Unix.hpp index 92306910..8f9a7fb7 100644 --- a/Source/IO/Net/AuNetResolver.Unix.hpp +++ b/Source/IO/Net/AuNetResolver.Unix.hpp @@ -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, 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; };