[+] 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"); 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 #endif
} }

View File

@ -11,6 +11,7 @@
#include <sys/socket.h> #include <sys/socket.h>
struct robust_list_head; struct robust_list_head;
struct glibc_aicb;
namespace Aurora 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 void (AU_NORETURN *p__cxa_throw)(void *pException, std::type_info *typeInfo, void (*fDtor)(void *pThis));
inline AuUInt32 (*p_Unwind_RaiseException)(void *pException); 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 }; int iInfoEx { 0 };
AuMemset(&this->infoEx, 0, sizeof(infoEx));
if (this->bA && this->bAAAA) if (this->bA && this->bAAAA)
{ {
infoEx.ai_family = AF_UNSPEC; infoEx.ai_family = AF_UNSPEC;
@ -136,6 +138,14 @@ namespace Aurora::IO::Net
return false; return false;
} }
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
if (!pgetaddrinfo_a)
{
return this->StartStandard();
}
sigevent event {0}; sigevent event {0};
event.sigev_notify = SIGEV_SIGNAL; event.sigev_notify = SIGEV_SIGNAL;
event.sigev_signo = GetGAIAsyncIOSignal(); event.sigev_signo = GetGAIAsyncIOSignal();
@ -160,28 +170,38 @@ namespace Aurora::IO::Net
pBase->ar_request = (addrinfo *)&infoEx; pBase->ar_request = (addrinfo *)&infoEx;
pBase->ar_name = hostname.c_str(); pBase->ar_name = hostname.c_str();
AuTryInsert(tlsResolvers, AuSharedFromThis()); if (!AuTryInsert(tlsResolvers, AuSharedFromThis()))
{
SysPushErrorMemory();
return false;
}
int iStatus = ::getaddrinfo_a(GAI_NOWAIT, int iStatus = pgetaddrinfo_a(GAI_NOWAIT,
&pBase, &pBase,
1, 1,
&event); &event);
switch (iStatus) switch (iStatus)
{ {
case EAI_AGAIN: case EAI_AGAIN:
{ {
SysPushErrorNet("Low Resources | Failed to resolve"); SysPushErrorNet("Low Resources | Failed to resolve");
this->uOsError = iStatus;
this->error_ = this->ToError();
return false; return false;
} }
case EAI_MEMORY: case EAI_MEMORY:
{ {
SysPushErrorNet("Out of Memory | Failed to resolve"); SysPushErrorNet("Out of Memory | Failed to resolve");
this->uOsError = iStatus;
this->error_ = this->ToError();
return false; return false;
} }
case EAI_SYSTEM: case EAI_SYSTEM:
{ {
SysPushErrorNet("Invalid | Failed to resolve"); SysPushErrorNet("Invalid | Failed to resolve: {}", errno);
this->uOsError = errno;
this->error_ = this->ToError();
return false; return false;
} }
} }
@ -189,12 +209,87 @@ namespace Aurora::IO::Net
if (iStatus != 0) if (iStatus != 0)
{ {
SysPushErrorNet("{}", iStatus); SysPushErrorNet("{}", iStatus);
this->uOsError = iStatus;
this->error_ = this->ToError();
return false; return false;
} }
return this->BeginOperation(AuSharedFromThis(), return this->BeginOperation(AuSharedFromThis(),
this->pWorker_); 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) void NetResolver::SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback)
@ -282,28 +377,58 @@ namespace Aurora::IO::Net
bool NetResolver::CheckAsync() 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) || return ((iStatus == 0) ||
(iStatus == EAI_CANCELED)); (iStatus == EAI_CANCELED));
#else
return !this->bForceError_;
#endif
} }
void NetResolver::Cancel() void NetResolver::Cancel()
{ {
while (!this->HasComplete()) while (!this->HasComplete())
{ {
int iStatus = ::gai_cancel(&this->gnuAsyncOperation); #if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
switch (iStatus)
if (pgai_cancel)
{ {
case EAI_CANCELED: int iStatus = pgai_cancel(&this->gnuAsyncOperation);
case EAI_ALLDONE: switch (iStatus)
break;
case EAI_NOTCANCELED:
{ {
IOYield(); case EAI_CANCELED:
AuThreading::ContextYield(); case EAI_ALLDONE:
continue; 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; return false;
} }
freeaddrinfo(pItr);
} }
return true; return true;
} }
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
static void Annoying(int) static void Annoying(int)
{ {
for (const auto &gawad : tlsResolvers) for (const auto &gawad : tlsResolvers)
@ -350,15 +479,21 @@ namespace Aurora::IO::Net
} }
} }
#endif
void InitFreetardedResolver() void InitFreetardedResolver()
{ {
#if defined(AURORA_HAS_GLIBC_RESOLVER_PROXY_STUBS)
struct sigaction action = struct sigaction action =
{ {
.sa_handler = Annoying, .sa_handler = Annoying,
.sa_flags = SA_ONSTACK .sa_flags = SA_ONSTACK | SA_RESTART
}; };
::sigemptyset(&action.sa_mask); ::sigemptyset(&action.sa_mask);
::sigaction(GetGAIAsyncIOSignal(), &action, nullptr); ::sigaction(GetGAIAsyncIOSignal(), &action, nullptr);
#endif
} }
} }

View File

@ -10,6 +10,27 @@
#include "AuNetSocketOverlappedOperation.hpp" #include "AuNetSocketOverlappedOperation.hpp"
#include "AuNetSocket.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 namespace Aurora::IO::Net
{ {
struct Socket; struct Socket;
@ -30,6 +51,7 @@ namespace Aurora::IO::Net
AuString hostname; AuString hostname;
bool Start(); bool Start();
bool StartStandard();
void SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback); void SetCompletion(const AuSPtr<AuAsync::PromiseCallback<AuList<IPAddress>, NetError>> &callback);
@ -52,10 +74,9 @@ namespace Aurora::IO::Net
bool bHasCompleted_ {}; bool bHasCompleted_ {};
bool bHasUnpackedEarly {}; bool bHasUnpackedEarly {};
NetError error_; NetError error_;
addrinfo infoEx { };
addrinfo infoEx { 0 }; bool bForceError_ {};
glibc_aicb gnuAsyncOperation {}; // freetarded
gaicb gnuAsyncOperation {}; // freetarded
bool CheckAsync(); bool CheckAsync();
friend struct ThreadLocalCaughtCompletion; friend struct ThreadLocalCaughtCompletion;
}; };