AuroraRuntime/Source/IO/Net/AuNetAdapter.NT.cpp

193 lines
5.5 KiB
C++
Raw Normal View History

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuNetAdapter.NT.cpp
Date: 2022-11-14
Author: Reece
***/
#include "Networking.hpp"
#include "AuNetAdapter.hpp"
#include "AuNetEndpoint.hpp"
#include <winsock2.h>
#include <iphlpapi.h>
namespace Aurora::IO::Net
{
static AuList<AuSPtr<INetAdapter>> gIpv4Adapters;
static AuList<AuSPtr<INetAdapter>> gIpv6Adapters;
AuString NetAdapter::GetHostname()
{
#if defined(AURORA_PLATFORM_WIN32)
wchar_t buffer[128];
DWORD dwLength { AuArraySize(buffer) };
if (!::GetComputerNameExW(ComputerNameDnsHostname, buffer, &dwLength))
{
return {};
}
return AuLocale::ConvertFromWChar(buffer, dwLength);
#else
return "";
#endif
}
#if defined(AURORA_PLATFORM_WIN32)
AuSPtr<IP_ADAPTER_ADDRESSES> GetAddressesForFamily(ULONG uFamily)
{
static const auto kDefSize = 15 * 1024;
AuSPtr<IP_ADAPTER_ADDRESSES> pAddresses;
DWORD outBufLen { kDefSize };
DWORD dwRetVal;
DWORD dwFlags = GAA_FLAG_INCLUDE_PREFIX | GAA_FLAG_INCLUDE_GATEWAYS;
DWORD dwIterations {};
do
{
pAddresses = AuReinterpretCast<IP_ADAPTER_ADDRESSES>(AuMakeSharedArray<AuUInt8>(kDefSize));
SysAssert(pAddresses);
dwRetVal = ::GetAdaptersAddresses(uFamily, dwFlags, NULL, pAddresses.get(), &outBufLen);
if (dwRetVal == 0)
{
break;
}
else if (dwRetVal != ERROR_BUFFER_OVERFLOW)
{
}
else
{
SysPushErrorNet("Fail");
break;
}
dwIterations++;
}
while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (dwIterations < 5));
return dwRetVal == NO_ERROR ? pAddresses : AuSPtr<IP_ADAPTER_ADDRESSES> {};
}
AU_NOINLINE void AddressesToList(AuSPtr<IP_ADAPTER_ADDRESSES> pAddresses, AuList<AuSPtr<INetAdapter>> &adaptersOut)
{
auto pCurrAddresses = pAddresses.get();
adaptersOut.clear();
while (pCurrAddresses)
{
auto pAdapter = AuMakeSharedThrow<NetAdapter>();
auto &adapter = *pAdapter.get();
adapter.device = pCurrAddresses->AdapterName;
adapter.name = AuLocale::ConvertFromWChar(pCurrAddresses->FriendlyName);
auto pUnicast = pCurrAddresses->FirstUnicastAddress;
if (pUnicast)
{
NetEndpoint ep;
if (pUnicast->Address.iSockaddrLength <= sizeof(ep.hint))
{
AuMemcpy(ep.hint, pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength);
DeoptimizeEndpoint(ep);
}
adapter.address = ep.ip;
}
auto pMulticast = pCurrAddresses->FirstMulticastAddress;
if (pMulticast)
{
NetEndpoint ep;
if (pMulticast->Address.iSockaddrLength <= sizeof(ep.hint))
{
AuMemcpy(ep.hint, pMulticast->Address.lpSockaddr, pMulticast->Address.iSockaddrLength);
DeoptimizeEndpoint(ep);
}
adapter.broadcast = ep.ip;
}
auto pAnycast = pCurrAddresses->FirstAnycastAddress;
if (pAnycast)
{
NetEndpoint ep;
if (pAnycast->Address.iSockaddrLength <= sizeof(ep.hint))
{
AuMemcpy(ep.hint, pAnycast->Address.lpSockaddr, pAnycast->Address.iSockaddrLength);
DeoptimizeEndpoint(ep);
}
adapter.anycast = ep.ip;
}
auto pGateway = pCurrAddresses->FirstGatewayAddress;
if (pGateway)
{
NetEndpoint ep;
if (pGateway->Address.iSockaddrLength <= sizeof(ep.hint))
{
AuMemcpy(ep.hint, pGateway->Address.lpSockaddr, pGateway->Address.iSockaddrLength);
DeoptimizeEndpoint(ep);
}
adapter.gateway = ep.ip;
}
auto pDnsServers = pCurrAddresses->FirstDnsServerAddress;
if (pDnsServers)
{
do
{
NetEndpoint ep;
if (pDnsServers->Address.iSockaddrLength <= sizeof(ep.hint))
{
AuMemcpy(ep.hint, pDnsServers->Address.lpSockaddr, pDnsServers->Address.iSockaddrLength);
DeoptimizeEndpoint(ep);
}
adapter.dns.push_back(ep.ip);
}
while (pDnsServers = pDnsServers->Next);
}
adaptersOut.push_back(pAdapter);
pCurrAddresses = pCurrAddresses->Next;
}
}
#endif
static void PrecacheAdapters()
{
auto pAdaptersV4 = GetAddressesForFamily(AF_INET);
auto pAdaptersV6 = GetAddressesForFamily(AF_INET6);
AddressesToList(pAdaptersV4, gIpv4Adapters);
AddressesToList(pAdaptersV6, gIpv6Adapters);
}
AuList<AuSPtr<INetAdapter>> NetAdapter::GetIPv4s()
{
#if defined(AURORA_PLATFORM_WIN32)
PrecacheAdapters();
return gIpv4Adapters;
#else
return {};
#endif
}
AuList<AuSPtr<INetAdapter>> NetAdapter::GetIPv6s()
{
#if defined(AURORA_PLATFORM_WIN32)
return gIpv6Adapters;
#else
return {};
#endif
}
}