Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Clean-up code
  • Loading branch information
simonrozsival committed Jan 12, 2022
commit f9203dae78f560dc16654edbc3098bd043ccc4eb
Original file line number Diff line number Diff line change
Expand Up @@ -13,84 +13,61 @@ internal sealed class AndroidIPGlobalStatistics : IPGlobalStatistics
{
public AndroidIPGlobalStatistics(bool ipv4)
{
NetworkInterface[] networkInterfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces();
AndroidNetworkInterface[] networkInterfaces = NetworkInterfacePal.GetAndroidNetworkInterfaces();

foreach (NetworkInterface networkInterface in networkInterfaces)
foreach (var networkInterface in networkInterfaces)
{
var component = ipv4 ? NetworkInterfaceComponent.IPv4 : NetworkInterfaceComponent.IPv6;
if (networkInterface.Supports(component))
{
NumberOfInterfaces++;
}

if (networkInterface is AndroidNetworkInterface androidNetworkInterface)
foreach (UnixUnicastIPAddressInformation addressInformation in networkInterface.UnicastAddress)
{
foreach (UnixUnicastIPAddressInformation addressInformation in androidNetworkInterface.UnicastAddress)
bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork;
if (isIPv4 == ipv4)
{
bool isIPv4 = addressInformation.Address.AddressFamily == AddressFamily.InterNetwork;
if (isIPv4 == ipv4)
{
NumberOfIPAddresses++;
}
NumberOfIPAddresses++;
}
}

if (androidNetworkInterface.MulticastAddresess != null)
if (networkInterface.MulticastAddresess != null)
{
foreach (IPAddress address in networkInterface.MulticastAddresess)
{
foreach (IPAddress address in androidNetworkInterface.MulticastAddresess)
bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork;
if (isIPv4 == ipv4)
{
bool isIPv4 = address.AddressFamily == AddressFamily.InterNetwork;
if (isIPv4 == ipv4)
{
NumberOfIPAddresses++;
}
NumberOfIPAddresses++;
}
}
}
}
}

public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override int NumberOfInterfaces { get; }

public override int NumberOfIPAddresses { get; }

public override int DefaultTtl => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
public override bool ForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
public override int NumberOfRoutes => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long OutputPacketRequests => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long OutputPacketRoutingDiscards => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long OutputPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long OutputPacketsWithNoRoute => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketFragmentFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketReassembliesRequired => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketReassemblyFailures => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketReassemblyTimeout => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketsFragmented => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long PacketsReassembled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPackets => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsDelivered => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsDiscarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsForwarded => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsWithAddressErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsWithHeadersErrors => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override long ReceivedPacketsWithUnknownProtocol => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,23 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.IO;
using System.Runtime.Versioning;

namespace System.Net.NetworkInformation
{
internal sealed class AndroidIPv4InterfaceProperties : UnixIPv4InterfaceProperties
{
private readonly AndroidNetworkInterface _androidNetworkInterface;

public AndroidIPv4InterfaceProperties(AndroidNetworkInterface androidNetworkInterface)
: base(androidNetworkInterface)
{
_androidNetworkInterface = androidNetworkInterface;
Mtu = androidNetworkInterface._mtu;
}

public override int Mtu => _androidNetworkInterface._mtu;
public override int Mtu { get; }

[UnsupportedOSPlatform("android")]
public override bool IsAutomaticPrivateAddressingActive => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

[UnsupportedOSPlatform("android")]
public override bool IsAutomaticPrivateAddressingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

[UnsupportedOSPlatform("android")]
public override bool IsDhcpEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

[UnsupportedOSPlatform("android")]
public override bool IsForwardingEnabled => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

[UnsupportedOSPlatform("android")]
public override bool UsesWins => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using System.Net;

namespace System.Net.NetworkInformation
Expand All @@ -15,97 +10,45 @@ namespace System.Net.NetworkInformation
/// </summary>
internal sealed class AndroidNetworkInterface : UnixNetworkInterface
{
private OperationalStatus _operationalStatus;
private bool _supportsMulticast;
private long _speed;
internal int _mtu;
private NetworkInterfaceType _interfaceType = NetworkInterfaceType.Unknown;
internal readonly int _mtu;
private readonly AndroidIPInterfaceProperties _ipProperties;

internal AndroidNetworkInterface(string name, int index) : base(name)
internal unsafe AndroidNetworkInterface(string name, Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo)
: base(name)
{
_index = index;
_ipProperties = new AndroidIPInterfaceProperties(this);
}

public static unsafe NetworkInterface[] GetAndroidNetworkInterfaces()
{
int interfaceCount=0;
int addressCount=0;
Interop.Sys.NetworkInterfaceInfo * nii = null;
Interop.Sys.IpAddressInfo * ai = null;
IntPtr globalMemory = (IntPtr)null;

if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &nii, &addressCount, &ai) != 0)
_index = networkInterfaceInfo->InterfaceIndex;
if (networkInterfaceInfo->NumAddressBytes > 0)
{
string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage();
throw new NetworkInformationException(message);
_physicalAddress = new PhysicalAddress(new ReadOnlySpan<byte>(networkInterfaceInfo->AddressBytes, networkInterfaceInfo->NumAddressBytes).ToArray());
}

globalMemory = (IntPtr)nii;
try
{
NetworkInterface[] interfaces = new NetworkInterface[interfaceCount];
Dictionary<int, AndroidNetworkInterface> interfacesByIndex = new Dictionary<int, AndroidNetworkInterface>(interfaceCount);

for (int i = 0; i < interfaceCount; i++)
{
var ani = new AndroidNetworkInterface(Marshal.PtrToStringAnsi((IntPtr)nii->Name)!, nii->InterfaceIndex);
ani._interfaceType = (NetworkInterfaceType)nii->HardwareType;
ani._operationalStatus = (OperationalStatus)nii->OperationalState;
ani._mtu = nii->Mtu;
ani._speed = nii->Speed;
ani._supportsMulticast = nii->SupportsMulticast != 0;

if (nii->NumAddressBytes > 0)
{
ani._physicalAddress = new PhysicalAddress(new ReadOnlySpan<byte>(nii->AddressBytes, nii->NumAddressBytes).ToArray());
}

interfaces[i] = ani;
interfacesByIndex.Add(nii->InterfaceIndex, ani);
nii++;
}

while (addressCount != 0)
{
var address = new IPAddress(new ReadOnlySpan<byte>(ai->AddressBytes, ai->NumAddressBytes));
if (address.IsIPv6LinkLocal)
{
address.ScopeId = ai->InterfaceIndex;
}

if (interfacesByIndex.TryGetValue(ai->InterfaceIndex, out AndroidNetworkInterface? ani))
{
ani.AddAddress(address, ai->PrefixLength);
}
_mtu = networkInterfaceInfo->Mtu;
_ipProperties = new AndroidIPInterfaceProperties(this);

ai++;
addressCount--;
}
OperationalStatus = (OperationalStatus)networkInterfaceInfo->OperationalState;
Speed = networkInterfaceInfo->Speed;
SupportsMulticast = networkInterfaceInfo->SupportsMulticast != 0;
NetworkInterfaceType = (NetworkInterfaceType)networkInterfaceInfo->HardwareType;
}

return interfaces;
}
finally
internal unsafe void AddAddress(Interop.Sys.IpAddressInfo *addressInfo)
{
var address = new IPAddress(new ReadOnlySpan<byte>(addressInfo->AddressBytes, addressInfo->NumAddressBytes));
if (address.IsIPv6LinkLocal)
{
Marshal.FreeHGlobal(globalMemory);
address.ScopeId = addressInfo->InterfaceIndex;
}
}

public override bool SupportsMulticast => _supportsMulticast;
AddAddress(address, addressInfo->PrefixLength);
}

public override bool SupportsMulticast { get; }
public override IPInterfaceProperties GetIPProperties() => _ipProperties;

public override IPInterfaceStatistics GetIPStatistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override IPv4InterfaceStatistics GetIPv4Statistics() => throw new PlatformNotSupportedException(SR.net_InformationUnavailableOnPlatform);

public override OperationalStatus OperationalStatus { get { return _operationalStatus; } }

public override NetworkInterfaceType NetworkInterfaceType { get { return _interfaceType; } }

public override long Speed => _speed;

public override bool IsReceiveOnly { get { return false; } }
public override OperationalStatus OperationalStatus { get; }
public override NetworkInterfaceType NetworkInterfaceType { get; }
public override long Speed { get; }
public override bool IsReceiveOnly => false;
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace System.Net.NetworkInformation
{
internal static class NetworkInterfacePal
{
/// Returns objects that describe the network interfaces on the local computer.
public static NetworkInterface[] GetAllNetworkInterfaces()
{
return AndroidNetworkInterface.GetAndroidNetworkInterfaces();
}
public static NetworkInterface[] GetAllNetworkInterfaces() => GetAndroidNetworkInterfaces();

public static bool GetIsNetworkAvailable()
{
foreach (var ni in GetAllNetworkInterfaces())
foreach (var ni in GetAndroidNetworkInterfaces())
{
if (ni.NetworkInterfaceType == NetworkInterfaceType.Loopback
|| ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
Expand All @@ -29,23 +29,68 @@ public static bool GetIsNetworkAvailable()
return false;
}

public static int IPv6LoopbackInterfaceIndex { get { return LoopbackInterfaceIndex; } }
public static int IPv6LoopbackInterfaceIndex => LoopbackInterfaceIndex;

public static int LoopbackInterfaceIndex
{
get
{
NetworkInterface[] interfaces = AndroidNetworkInterface.GetAndroidNetworkInterfaces();
for (int i = 0; i < interfaces.Length; i++)
foreach (var networkInterface in GetAndroidNetworkInterfaces())
{
if (interfaces[i].NetworkInterfaceType == NetworkInterfaceType.Loopback)
if (networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback)
{
return ((UnixNetworkInterface)interfaces[i]).Index;
return networkInterface.Index;
}
}

throw new NetworkInformationException(SR.net_NoLoopback);
}
}

internal static unsafe AndroidNetworkInterface[] GetAndroidNetworkInterfaces()
{
int interfaceCount = 0;
int addressCount = 0;
Interop.Sys.NetworkInterfaceInfo *networkInterfaceInfo = null;
Interop.Sys.IpAddressInfo *addressInfo = null;

if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &networkInterfaceInfo, &addressCount, &addressInfo) != 0)
{
string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage();
throw new NetworkInformationException(message);
}

// the native implementation of Interop.Sys.GetNetworkInterfaces allocates one block of memory
// for both networkInterfaceInfo and addressInfo so we only need to call free once pointing at
// the start of the network itnerfaces list
var globalMemory = (IntPtr)networkInterfaceInfo;

try
{
var networkInterfaces = new AndroidNetworkInterface[interfaceCount];
var interfacesByIndex = new Dictionary<int, AndroidNetworkInterface>(interfaceCount);

for (int i = 0; i < interfaceCount; i++, networkInterfaceInfo++)
{
var name = Marshal.PtrToStringAnsi((IntPtr)networkInterfaceInfo->Name);
var networkInterface = new AndroidNetworkInterface(name!, networkInterfaceInfo);
networkInterfaces[i] = interfacesByIndex[networkInterface.Index] = networkInterface;
}

for (int i = 0; i < addressCount; i++, addressInfo++)
{
if (interfacesByIndex.TryGetValue(addressInfo->InterfaceIndex, out var networkInterface))
{
networkInterface.AddAddress(addressInfo);
}
}

return networkInterfaces;
}
finally
{
Marshal.FreeHGlobal(globalMemory);
}
}
}
}