#define TRACE using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; namespace ArchestrAServices.Common; public class IPAddressWatcher : IDisposable { private readonly ReaderWriterLockSlim cacheLock = new ReaderWriterLockSlim(); private List ipAddresses = new List(); private bool disposed; public event IPAddressChangeEventHandler AddressChangedEvent; public IPAddressWatcher() { ipAddresses = GetAllIpAddresses(); } ~IPAddressWatcher() { Dispose(disposing: false); } public void Start() { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Start watching for IP address changes"); NetworkChange.NetworkAddressChanged += IpChangedEventHandler; } public void Stop() { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Stop watching for IP address changes"); NetworkChange.NetworkAddressChanged -= IpChangedEventHandler; } public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } private static List GetAllIpAddresses() { List list = new List(); NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); for (int i = 0; i < allNetworkInterfaces.Length; i++) { foreach (UnicastIPAddressInformation unicastAddress in allNetworkInterfaces[i].GetIPProperties().UnicastAddresses) { if (unicastAddress.IsDnsEligible && unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, " Found IPV4 address = {0}", unicastAddress.Address); list.Add(unicastAddress.Address); } } } SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "Found a total of {0} IPV4 addresses", list.Count); return list; } private bool HaveIpAddressesChanged() { bool flag = false; List allIpAddresses = GetAllIpAddresses(); if (allIpAddresses.Count != ipAddresses.Count) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "IP Address count has changed: current count = {0}, previous count = {1}", allIpAddresses.Count, ipAddresses.Count); flag = true; } if (!flag) { foreach (IPAddress item in allIpAddresses) { if (!ipAddresses.Contains(item)) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "IP Address has changed: new address = {0} did not previously exist", item); flag = true; break; } } } if (!flag) { foreach (IPAddress ipAddress in ipAddresses) { if (!allIpAddresses.Contains(ipAddress)) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "IP Address has changed: old address = {0} no longer exists", ipAddress); flag = true; break; } } } if (flag) { SvcTrace.DiagDiagnostics.TraceEvent(TraceEventType.Information, 0, "IP Addresses Previous: {0} and current {1}", string.Join(",", ipAddresses.Select((IPAddress a) => a.ToString())), string.Join(",", allIpAddresses.Select((IPAddress a) => a.ToString()))); ipAddresses = allIpAddresses; } return flag; } private void IpChangedEventHandler(object sender, EventArgs e) { cacheLock.EnterWriteLock(); bool flag; try { flag = HaveIpAddressesChanged(); } finally { cacheLock.ExitWriteLock(); } if (flag) { TriggerNetworkAddressChanged(); } } private Task TriggerNetworkAddressChanged() { IPAddressChangeEventHandler handler = this.AddressChangedEvent; if (handler != null) { return Task.Factory.StartNew(delegate { handler(); }); } return Task.Factory.StartNew(delegate { }); } protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing && cacheLock != null) { cacheLock.Dispose(); } disposed = true; } } }