using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using Vanara.PInvoke.NetListMgr;
namespace Vanara.Network
{
/// Provides a set of methods to perform network list management functions.
public static partial class NetworkListManager
{
private static NetworkConnectionIterator connIter;
private static INetworkCostManager costmgr;
private static INetworkListManager manager;
private static NetworkIterator netIter;
/// An enumerable list that supports a length and indexer.
/// The type of the item.
/// The type of the parameter used by the indexer.
///
public interface IEnumerableList : IEnumerable
{
/// Gets the length of the list.
int Length { get; }
/// Gets the with the specified identifier.
/// The found item type.
/// The identifier.
/// The item found by the identifier.
T this[TLookup id] { get; }
}
/// Gets the current connectivity state.
/// The connectivity state.
public static NLM_CONNECTIVITY Connectivity => Manager?.GetConnectivity() ?? NLM_CONNECTIVITY.NLM_CONNECTIVITY_DISCONNECTED;
/// Gets a value indicating whether a network is connected.
/// true if a network is connected; otherwise, false.
public static bool IsConnected => Manager?.IsConnected ?? false;
/// Gets a value indicating whether connectivity to the Internet is available.
/// true if connectivity to the Internet is available; otherwise, false.
public static bool IsConnectedToInternet => Manager?.IsConnectedToInternet ?? false;
/// Gets the network connections for this device.
/// The network connections.
public static IEnumerableList NetworkConnections => connIter ?? (connIter = new NetworkConnectionIterator());
/// Gets the active networks available.
/// The networks.
public static IEnumerableList Networks => netIter ?? (netIter = new NetworkIterator());
///
/// Gets the current cost of either a machine-wide internet connection, or the first-hop of routing to a specific destination on a
/// connection. If destIPaddr is NULL, this method instead returns the cost of the network used for machine-wide Internet connectivity.
///
///
/// The destination IPv4/IPv6 address. If , this method will instead return the cost associated with the
/// preferred connection used for machine Internet connectivity.
///
/// The cost of the connection.
public static NLM_CONNECTION_COST GetConnectionCost(IPAddress destIPAddr = null)
{
var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr);
var cost = NLM_CONNECTION_COST.NLM_CONNECTION_COST_UNKNOWN;
(costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetCost(out cost, addr);
return cost;
}
///
/// Gets the data plan status for either a machine-wide internet connection , or the first-hop of routing to a specific destination
/// on a connection. If an IPv4/IPv6 address is not specified, this method returns the data plan status of the connection used for
/// machine-wide Internet connectivity.
///
///
/// The destination IPv4/IPv6 address. If , this method will instead return the data plan status of the
/// connection used for machine-wide Internet connectivity.
///
///
/// An NLM_DATAPLAN_STATUS structure that describes the data plan status associated with a connection used to route to a destination.
/// If destIPAddr specifies a tunnel address, the first available data plan status in the interface stack is returned.
///
public static NLM_DATAPLAN_STATUS GetConnectionDataPlanStatus(IPAddress destIPAddr = null)
{
var addr = NLM_SOCKADDR.FromIPAddress(destIPAddr);
var cost = new NLM_DATAPLAN_STATUS();
(costmgr ?? (costmgr = (INetworkCostManager)Manager))?.GetDataPlanStatus(out cost, addr);
return cost;
}
/// Gets a value indicating whether the data plan status values are default values, or provided by the MNO.
/// true if this instance is available; otherwise, false.
public static bool IsDefined(this NLM_DATAPLAN_STATUS status)
{
const uint NLM_UNKNOWN_DATAPLAN_STATUS = 0xFFFFFFFF;
// usage data is valid only if both planUsage and lastUpdatedTime are valid
if (status.UsageData.UsageInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS && (status.UsageData.LastSyncTime.dwHighDateTime != 0 || status.UsageData.LastSyncTime.dwLowDateTime != 0))
return true;
if (status.DataLimitInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS)
return true;
if (status.InboundBandwidthInKbps != NLM_UNKNOWN_DATAPLAN_STATUS)
return true;
if (status.OutboundBandwidthInKbps != NLM_UNKNOWN_DATAPLAN_STATUS)
return true;
if (status.NextBillingCycle.dwHighDateTime != 0 || status.NextBillingCycle.dwLowDateTime != 0)
return true;
if (status.MaxTransferSizeInMegabytes != NLM_UNKNOWN_DATAPLAN_STATUS)
return true;
return false;
}
internal static INetworkListManager Manager
{
get
{
if (manager != null) return manager;
try
{
manager = new INetworkListManager();
}
catch (UnauthorizedAccessException) { }
catch (ExternalException) { }
return manager;
}
}
internal class NetworkConnectionIterator : IEnumerableList, IDisposable
{
private IEnumNetworkConnections conns;
internal NetworkConnectionIterator(IEnumNetworkConnections conns = null)
{
this.conns = conns;
}
public int Length => Items.Count();
private IEnumerable Items => GetItems(conns);
private static IEnumerable GetItems(IEnumNetworkConnections conns)
{
IEnumerable ie = null;
try
{
ie = (conns ?? Manager?.GetNetworkConnections()).Cast().Select(i => new NetworkConnection(i));
}
catch (UnauthorizedAccessException) { }
catch (ExternalException) { }
return ie;
}
public NetworkConnection this[Guid id] => new NetworkConnection(Manager?.GetNetworkConnection(id));
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator GetEnumerator()
{
var ie = Items;
if (ie == null) yield break;
foreach (var conn in ie)
yield return conn;
}
void IDisposable.Dispose()
{
if (conns == null) return;
Marshal.FinalReleaseComObject(conns);
conns = null;
}
}
private class NetworkIterator : IEnumerableList
{
internal NetworkIterator()
{
}
public int Length => Items.Count();
private static IEnumerable Items
{
get
{
IEnumerable ie = null;
try
{
ie = Manager?.GetNetworks(NLM_ENUM_NETWORK.NLM_ENUM_NETWORK_ALL).Cast().Select(i => new NetworkProfile(i));
}
catch (UnauthorizedAccessException) { }
catch (ExternalException) { }
return ie;
}
}
public NetworkProfile this[Guid id] => new NetworkProfile(Manager?.GetNetwork(id));
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator GetEnumerator()
{
var ie = Items;
if (ie == null) yield break;
foreach (var networkProfile in ie)
yield return networkProfile;
}
}
}
}