using System; using ln.application; using ln.application.service; using System.Threading; using ln.types.odb.ng; using ln.types; using System.Collections.Generic; using System.Linq; using ln.json; using ln.types.odb.ng.storage.session; using ln.types.net; namespace ln.provider { public class IPPoolService : ApplicationServiceBase { CoreService CoreService { get; set; } ProviderApplication Application => base.CurrentApplication as ProviderApplication; RPC rpc; SessionStorageContainer mapperSession; Mapper mapper; IPAllocation v6Root; IPAllocation v4Root; public IPPoolService() :base("IPPoolService") { DependOnService(); rpc = new RPC(this); } public override void ServiceMain(Application applicationInterface) { CoreService = Dependency(); using (mapperSession = new SessionStorageContainer(CoreService.CoreStorageContainer)) { mapper = new Mapper(mapperSession); mapper.EnsureIndex("CIDR"); mapper.EnsureIndex("Pool"); Application.RPCContainer.Add("ippool", rpc); v6Root = mapper.Load(Query.Equals("CIDR",IPv6.ANY)).FirstOrDefault(); v4Root = mapper.Load(Query.Equals("CIDR", IPv6.V4Space)).FirstOrDefault(); if (v6Root == null) { v6Root = new IPAllocation(IPv6.ANY, "Global IPv6 Space", null); mapper.Save(v6Root); } if (v4Root == null) { v4Root = new IPAllocation(IPv6.V4Space, "Global IPv4 Space", v6Root.CIDR); mapper.Save(v4Root); } Ready(); while (!StopRequested) { lock (Thread.CurrentThread) { Monitor.Wait(Thread.CurrentThread); } } } mapper = null; Application.RPCContainer.Remove("ippool"); CoreService = null; } public IPAllocation[] GetAllocations() { return mapper.Load().ToArray(); } public IPAllocation GetAllocation(IPv6 cidr) { return mapper.Load(Query.Equals("CIDR", cidr)).FirstOrDefault(); } public IPAllocation[] GetPoolAllocations(IPv6 pool) { return mapper.Load(Query.Equals("Pool", pool)).ToArray(); } public IPAllocation AllocateAny(IPv6 zone,int width,string usage) { return null; } public IPAllocation AllocateCIDR(IPv6 zone,IPv6 cidr,string usage,bool splitZones) { IPAllocation pool = GetAllocation(zone); if (pool == null) throw new KeyNotFoundException(); if (!pool.CIDR.Contains(cidr)) throw new ArgumentException(String.Format("{0} doesn't contain {1}", pool.CIDR.ToCIDR(), cidr.ToCIDR())); if (splitZones) { IPAllocation allocation = pool; while (!allocation.CIDR.Equals(cidr)) { IPAllocation split = null; foreach (IPv6 splitCIDR in allocation.CIDR.Split(1)) { if (splitCIDR.Contains(cidr)) { split = GetAllocation(splitCIDR); if (split == null) { split = new IPAllocation(splitCIDR,allocation.CIDR); mapper.Save(split); break; } else if (Equals(String.Empty,split.AllocatedTo)) { break; } throw new ArgumentOutOfRangeException(String.Format("No subnet available below {0}",allocation.CIDR.ToCIDR())); } } allocation = split; } allocation.AllocatedTo = usage; mapper.Save(allocation); return allocation; } else { IPAllocation allocation = GetAllocation(cidr); if (allocation != null) throw new Exception("Allocation already present"); allocation = new IPAllocation(cidr, cidr.ToCIDR(), pool.CIDR); allocation.AllocatedTo = usage; mapper.Save(allocation); return allocation; } } class RPC { IPPoolService poolService; public RPC(IPPoolService poolService) { this.poolService = poolService; } public IPAllocation[] GetAllocations() => poolService.GetAllocations(); public IPAllocation GetAllocation(IPv6 cidr) => poolService.GetAllocation(cidr); public IPAllocation[] GetPoolAllocations(IPv6 pool) => poolService.GetPoolAllocations(pool); public IPAllocation AllocateAny(IPv6 zone, int width, string usage) => poolService.AllocateAny(zone, width, usage); public IPAllocation AllocateCIDR(IPv6 zone, IPv6 cidr, string usage, bool splitZones) => poolService.AllocateCIDR(zone, cidr, usage,splitZones); } public class IPAllocation { public IPv6 CIDR { get; } public string Name { get; set; } = String.Empty; public string AllocatedTo { get; set; } = String.Empty; public IPv6 Pool { get; } private IPAllocation(){} public IPAllocation(IPv6 cidr): this(cidr, cidr.ToCIDR(), IPv6.ANY) { } public IPAllocation(IPv6 cidr, IPv6 pool) : this(cidr, cidr.ToCIDR(), pool) { } public IPAllocation(IPv6 cidr,String name,IPv6 pool) { Pool = pool; CIDR = cidr; Name = name; } } } }