ln.skyscanner/entities/HopMap.cs

208 lines
5.5 KiB
C#

// /**
// * File: HopMap.cs
// * Author: haraldwolff
// *
// * This file and it's content is copyrighted by the Author and / or copyright holder.
// * Any use wihtout proper permission is illegal and may lead to legal actions.
// *
// *
// **/
using System;
using System.Collections.Generic;
using System.Collections;
using Castle.Core.Logging;
using ln.types.odb;
using System.Linq;
using ln.types.btree;
using Castle.Components.DictionaryAdapter.Xml;
using Newtonsoft.Json;
using ln.types.net;
using System.Net.Sockets;
namespace ln.skyscanner.entities
{
public class HopMap : Persistent
{
public Node TopNode { get; private set; }
public GlobalNetwork GlobalNetwork => SkyScanner.Instance.Entities.GlobalNetwork;
public int MaxDepth { get; set; } = 16;
private BTree<Node, HopNode> hopNodes = new BTree<Node, HopNode>(CompareNodes);
private HashSet<Network4> networks = new HashSet<Network4>();
public HopMap()
{
}
public HopMap(Node node)
{
Reset(node);
}
public void Reset(Node node)
{
hopNodes.Clear();
TopNode = node;
HopNode hopNode = new HopNode(this, node);
}
public int GetHopCount(Node node)
{
if (!hopNodes.ContainsKey(node))
return -1;
return hopNodes[node].HopCount;
}
public HopNode[] HopNodes
{
get
{
return hopNodes.Values.ToArray();
}
}
public class HopNode : IComparable
{
[JsonIgnore]
public HopMap HopMap { get; }
[JsonIgnore]
public HopNode Parent { get; private set; }
public Node Node;
[JsonIgnore]
public HopNode[] Peers => peers.ToArray();
private HashSet<HopNode> peers = new HashSet<HopNode>();
private int hopCount = 0;
public HopNode(HopMap hopMap, Node node)
{
HopMap = hopMap;
Node = node;
HopMap.hopNodes.Add(node, this);
FindPeers();
}
public HopNode(HopNode parent, Node node)
{
HopMap = parent.HopMap;
Node = node;
Attach(parent);
FindPeers();
}
private void FindPeers()
{
foreach (Network4 network in Node.Networks)
{
EnsureNetwork(network);
}
EnsureNetwork(HopMap.GlobalNetwork.FindSubnetForIP(Node.PrimaryIP).Network);
}
private void EnsureNetwork(Network4 network)
{
if (!HopMap.networks.Contains(network))
{
HopMap.networks.Add(network);
FindPeers(network);
}
}
private void FindPeers(Network4 network)
{
foreach (Node peerNode in HopMap.GlobalNetwork.FindHostsInSubnet(network))
{
if (!HopMap.hopNodes.ContainsKey(peerNode))
{
new HopNode(this, peerNode);
}
else
{
HopNode existingHopNode = HopMap.hopNodes[peerNode];
if (existingHopNode.HopCount > (HopCount + 1))
{
existingHopNode.Detach();
existingHopNode.Attach(this);
}
}
}
}
public int HopCount
{
get => hopCount;
set
{
hopCount = value;
foreach (HopNode peer in peers)
{
peer.HopCount = hopCount + 1;
}
}
}
public void Attach(HopNode parent)
{
Detach();
Parent = parent;
if (!Object.ReferenceEquals(null, Parent))
{
HopMap.hopNodes.Add(this.Node, this);
Parent.peers.Add(this);
HopCount = parent.hopCount + 1;
}
else
{
HopCount = 0;
}
}
public void Detach()
{
if (!Object.ReferenceEquals(null, Parent))
{
Parent.peers.Remove(this);
Parent = null;
HopMap.hopNodes.Remove(this.Node);
}
}
public int CompareTo(object obj)
{
if (obj is HopNode)
{
HopNode you = obj as HopNode;
return Node.ID.CompareTo(you.Node.ID);
}
return this.GetHashCode() - obj.GetHashCode();
}
public IPv4[] Path => _path().ToArray();
private List<IPv4> _path()
{
if (Parent == null)
return new List<IPv4>(new IPv4[] { Node.PrimaryIP });
List<IPv4> l = Parent._path();
l.Add(Node.PrimaryIP);
return l;
}
}
private static int CompareNodes(Node a, Node b)
{
return a.ID.CompareTo(b.ID);
}
}
}