Skip to content

Commit

Permalink
Introduce network scan support for exotic networks
Browse files Browse the repository at this point in the history
Previously only A.B.C.1-255 was supported / assumed.
  • Loading branch information
nwoolls committed Dec 27, 2014
1 parent bf0d5c1 commit 600321d
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 36 deletions.
6 changes: 6 additions & 0 deletions MultiMiner.Utility/Net/IPRange.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ public IPRange(string ipRange)
throw new ArgumentException();
}

public IPRange(IPAddress startingIp, IPAddress endingIp)
{
beginIp = startingIp.GetAddressBytes();
endIp = endingIp.GetAddressBytes();
}

public IEnumerable<IPAddress> GetIPAddresses()
{
int capacity = 1;
Expand Down
88 changes: 60 additions & 28 deletions MultiMiner.Utility/Net/LocalNetwork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,91 @@
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;

namespace MultiMiner.Utility.Net
{
public class LocalNetwork
{
public struct NetworkInterfaceInfo
{
public IPAddress Host;
public IPAddress Netmask;
public IPAddress Broadcast;
public IPAddress RangeStart;
public IPAddress RangeEnd;
}

public static string GetLocalIPAddress()
{
return GetLocalIPAddresses().FirstOrDefault();
}

public static List<string> GetLocalIPAddresses()
public static IPAddress GetBroadcastAddress(IPAddress address, IPAddress subnetMask)
{
List<string> result = new List<string>();
byte[] ipAdressBytes = address.GetAddressBytes();
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();

IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if ((ip.AddressFamily == AddressFamily.InterNetwork) &&
//don't include loopback address, e.g. 127.0.0.1
(!IPAddress.IsLoopback(ip)))
result.Add(ip.ToString());
}
if (ipAdressBytes.Length != subnetMaskBytes.Length)
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");

return result;
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++)
broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));

return new IPAddress(broadcastAddress);
}

public static string GetLocalIPAddressRange(string localIpAddress)
public static List<NetworkInterfaceInfo> GetLocalNetworkInterfaces()
{
if (String.IsNullOrEmpty(localIpAddress))
return String.Empty;
List<NetworkInterfaceInfo> result = new List<NetworkInterfaceInfo>();

string[] portions = localIpAddress.Split('.');
portions[portions.Length - 1] = "1-255";
NetworkInterface[] networkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in networkInterfaces)
{
if ((networkInterface.NetworkInterfaceType == NetworkInterfaceType.Loopback) ||
(networkInterface.NetworkInterfaceType == NetworkInterfaceType.Tunnel) ||
(networkInterface.OperationalStatus != OperationalStatus.Up))
continue;

return String.Join(".", portions);
}
IPInterfaceProperties ipProperties = networkInterface.GetIPProperties();
foreach (UnicastIPAddressInformation ipInformation in ipProperties.UnicastAddresses)
{
IPAddress ipAddress = ipInformation.Address;

public static string GetLocalIPAddressRange()
{
return GetLocalIPAddressRange(GetLocalIPAddress());
}
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
NetworkInterfaceInfo interfaceInfo = new NetworkInterfaceInfo();

public static List<string> GetLocalIPAddressRanges()
{
List<string> result = new List<string>();
interfaceInfo.Host = ipAddress;
interfaceInfo.Netmask = ipInformation.IPv4Mask;
interfaceInfo.Broadcast = GetBroadcastAddress(interfaceInfo.Host, interfaceInfo.Netmask);

List<string> localIPAddresses = GetLocalIPAddresses();
foreach (string localIPAddress in localIPAddresses)
result.Add(GetLocalIPAddressRange(localIPAddress));
//deprecations are known - we only support IPv4 scanning with this code
//see above check for AddressFamily.InterNetwork
long host = (long)(uint)IPAddress.NetworkToHostOrder((int)interfaceInfo.Host.Address);
long netmask = (long)(uint)IPAddress.NetworkToHostOrder((int)interfaceInfo.Netmask.Address);
long broadcast = (long)(uint)IPAddress.NetworkToHostOrder((int)interfaceInfo.Broadcast.Address);
long network = host & netmask;
long rangeStart = network + 1;
long rangeEnd = broadcast - 1;

interfaceInfo.RangeStart = new IPAddress((long)(uint)IPAddress.HostToNetworkOrder((int)rangeStart));
interfaceInfo.RangeEnd = new IPAddress((long)(uint)IPAddress.HostToNetworkOrder((int)rangeEnd));

result.Add(interfaceInfo);
}
}
}

return result;
}

public static List<string> GetLocalIPAddresses()
{
return GetLocalNetworkInterfaces().Select(ni => ni.Host.ToString()).ToList();
}

public static string GetWorkGroupName()
{
string result = String.Empty;
Expand Down
6 changes: 3 additions & 3 deletions MultiMiner.Utility/Net/PortScanner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ namespace MultiMiner.Utility.Net
{
public class PortScanner
{
public static List<IPEndPoint> Find(string ipRange, int startingPort, int endingPort, int connectTimeout = 100)
public static List<IPEndPoint> Find(IPAddress startingIp, IPAddress endingIp, int startingPort, int endingPort, int connectTimeout = 100)
{
if (startingPort > endingPort)
throw new ArgumentException();

List<IPEndPoint> endpoints = new List<IPEndPoint>();

List<IPAddress> ipAddresses = new IPRange(ipRange).GetIPAddresses().ToList();
List<IPAddress> ipAddresses = new IPRange(startingIp, endingIp).GetIPAddresses().ToList();

//optimize until we need otherwise
ipAddresses.RemoveAll(ip => LocalNetwork.GetLocalIPAddresses().Contains(ip.Address.ToString()));
ipAddresses.RemoveAll(ip => LocalNetwork.GetLocalIPAddresses().Contains(ip.ToString()));
ipAddresses.RemoveAll(ip => ip.ToString().EndsWith(".0"));

foreach (IPAddress ipAddress in ipAddresses)
Expand Down
6 changes: 3 additions & 3 deletions MultiMiner.Win/Forms/MinerForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1767,16 +1767,16 @@ private void SetupNetworkDeviceDetection()

private void FindNetworkDevices()
{
List<string> localIpRanges = Utility.Net.LocalNetwork.GetLocalIPAddressRanges();
List<Utility.Net.LocalNetwork.NetworkInterfaceInfo> localIpRanges = Utility.Net.LocalNetwork.GetLocalNetworkInterfaces();
if (localIpRanges.Count == 0)
return; //no network connection

const int startingPort = 4028;
const int endingPort = 4030;

foreach (string localIpRange in localIpRanges)
foreach (Utility.Net.LocalNetwork.NetworkInterfaceInfo interfaceInfo in localIpRanges)
{
List<IPEndPoint> miners = MinerFinder.Find(localIpRange, startingPort, endingPort);
List<IPEndPoint> miners = MinerFinder.Find(interfaceInfo.RangeStart, interfaceInfo.RangeEnd, startingPort, endingPort);

//remove own miners
miners.RemoveAll(m => Utility.Net.LocalNetwork.GetLocalIPAddresses().Contains(m.Address.ToString()));
Expand Down
4 changes: 2 additions & 2 deletions MultiMiner.Xgminer.Discovery/MinerFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ namespace MultiMiner.Xgminer.Discovery
{
public class MinerFinder
{
public static List<IPEndPoint> Find(string ipRange, int startingPort, int endingPort)
public static List<IPEndPoint> Find(IPAddress startingIp, IPAddress endingIp, int startingPort, int endingPort)
{
if (startingPort > endingPort)
throw new ArgumentException();

List<IPEndPoint> endpoints = PortScanner.Find(ipRange, startingPort, endingPort);
List<IPEndPoint> endpoints = PortScanner.Find(startingIp, endingIp, startingPort, endingPort);
List<IPEndPoint> miners = new List<IPEndPoint>();

foreach (IPEndPoint ipEndpoint in endpoints)
Expand Down

0 comments on commit 600321d

Please sign in to comment.