public bool?Update(DateTime utcNow, long counter, bool simulateFailure) { bool?result = null; PeerGroup peerGroup = this.Location.PeerGroup; if (peerGroup.CanPoll(utcNow, this.lastPolled)) { bool?wasConnected = this.IsConnected; using (Pinger pinger = new Pinger(peerGroup.Wait)) { TimeSpan roundtripTime = TimeSpan.Zero; this.IsConnected = !simulateFailure && pinger.TryPing(this.Location.Address, out roundtripTime); this.RoundtripTime = roundtripTime; this.UpdateCounter = counter; } result = this.IsConnected != wasConnected; this.lastPolled = utcNow; } return(result); }
private bool FindPeerGroupState(PeerGroup peerGroup, out PeerGroupState state) { state = this.PeerGroups.FirstOrDefault(s => s.PeerGroup == peerGroup); return(state != null); }
private void PeerGroupsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { List <Location> toRemove = null; switch (e.Action) { case NotifyCollectionChangedAction.Remove: // Remove any locations using the removed peer groups. The UI should prevent this from occurring. IEnumerable <PeerGroup> oldItems = e.OldItems.Cast <PeerGroup>(); toRemove = new List <Location>(); foreach (Location location in this.Locations.Where(l => oldItems.Any(g => g == l.PeerGroup))) { toRemove.Add(location); } break; case NotifyCollectionChangedAction.Replace: // Replace any locations that are using the replaced peer groups. oldItems = e.OldItems.Cast <PeerGroup>(); IEnumerable <PeerGroup> newItems = e.NewItems.Cast <PeerGroup>(); var pairs = oldItems.Zip(newItems, (o, n) => Tuple.Create(o, n)).ToArray(); int numLocations = this.Locations.Count; for (int i = 0; i < numLocations; i++) { Location currentLocation = this.Locations[i]; PeerGroup replacement = pairs.FirstOrDefault(p => p.Item1 == currentLocation.PeerGroup)?.Item2; if (replacement != null) { this.Locations[i] = new Location(replacement, currentLocation.Name, currentLocation.Address, currentLocation.Id); } } break; case NotifyCollectionChangedAction.Reset: // Update all locations. Use latest peer group with matching Id. Delete non-matches. numLocations = this.Locations.Count; var idToGroupMap = this.PeerGroups.ToDictionary(g => g.Id); toRemove = new List <Location>(); for (int i = 0; i < numLocations; i++) { Location currentLocation = this.Locations[i]; if (idToGroupMap.TryGetValue(currentLocation.PeerGroup.Id, out PeerGroup replacement)) { this.Locations[i] = new Location(replacement, currentLocation.Name, currentLocation.Address, currentLocation.Id); } else { toRemove.Add(currentLocation); } } break; } foreach (Location location in toRemove ?? Enumerable.Empty <Location>()) { this.Locations.Remove(location); } }
private void LoadDefaults() { void AddLocation(Location location) { // Don't add a duplicate address (e.g., both router and modem if they're the same). if (!this.Locations.Any(l => l.Address.Equals(location.Address))) { if (!this.PeerGroups.Contains(location.PeerGroup)) { this.PeerGroups.Add(location.PeerGroup); } this.Locations.Add(location); } } XElement root = XElement.Parse(Properties.Resources.DefaultProfileXml); foreach (XElement groupElement in root.Elements(nameof(PeerGroup))) { string groupName = groupElement.GetAttributeValue("Name"); #pragma warning disable MEN010 // Avoid magic numbers. Default times are clear in context. int failSeconds = groupElement.GetAttributeValue("FailSeconds", 10); int pollSeconds = groupElement.GetAttributeValue("PollSeconds", 5); int waitMilliseconds = groupElement.GetAttributeValue("WaitMilliseconds", 200); #pragma warning restore MEN010 // Avoid magic numbers PeerGroup group = new PeerGroup( groupName, TimeSpan.FromSeconds(failSeconds), TimeSpan.FromSeconds(pollSeconds), TimeSpan.FromMilliseconds(waitMilliseconds)); foreach (XElement locationElement in groupElement.Elements(nameof(Location))) { string locationName = locationElement.GetAttributeValue("Name"); int ordinal = 1; foreach (XElement addressElement in locationElement.Elements("Address")) { if (IPAddress.TryParse(addressElement.Value, out IPAddress address)) { string nameSuffix = ordinal == 1 ? string.Empty : $" #{ordinal}"; Location location = new Location(group, locationName + nameSuffix, address); AddLocation(location); ordinal++; } } } foreach (XElement findElement in groupElement.Elements("Find")) { string findName = findElement.GetAttributeValue("Name"); string findType = findElement.GetAttributeValue("Type"); IPAddress address; switch (findType) { case "DefaultGateway": // The first IP address returned by a traceroute should be the gateway. https://stackoverflow.com/a/29494180/1882616 // We'll simulate that by doing a ping with TTL = 1. https://stackoverflow.com/a/45565253/1882616 address = Pinger.GetAddressAtTtl(IPAddress.Parse("8.8.8.8"), 1, group.Wait); break; case "CableModem": using (Pinger pinger = new Pinger(group.Wait)) { address = findElement.Elements("Address").Select(e => IPAddress.Parse(e.Value)).FirstOrDefault(a => pinger.TryPing(a) ?? false); } break; default: throw Exceptions.NewInvalidOperationException($"Unsupported Find Type: {findType}"); } if (address != null) { Location location = new Location(group, findName, address); AddLocation(location); } } } }
internal PeerGroupState(PeerGroup peerGroup) { this.PeerGroup = peerGroup; this.UpdateCounter = -1; }