2022-12-14 20:08:52 +00:00
|
|
|
/***
|
|
|
|
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();
|
|
|
|
|
2022-12-15 01:49:26 +00:00
|
|
|
adaptersOut.clear();
|
|
|
|
|
2022-12-14 20:08:52 +00:00
|
|
|
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;
|
2022-12-15 01:49:26 +00:00
|
|
|
if (pGateway)
|
2022-12-14 20:08:52 +00:00
|
|
|
{
|
|
|
|
NetEndpoint ep;
|
|
|
|
if (pGateway->Address.iSockaddrLength <= sizeof(ep.hint))
|
|
|
|
{
|
|
|
|
AuMemcpy(ep.hint, pGateway->Address.lpSockaddr, pGateway->Address.iSockaddrLength);
|
|
|
|
DeoptimizeEndpoint(ep);
|
|
|
|
}
|
|
|
|
|
2022-12-15 01:49:26 +00:00
|
|
|
adapter.gateway = ep.ip;
|
2022-12-14 20:08:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|