/* Technitium DNS Server Copyright (C) 2022 Shreyas Zare (shreyas@technitium.com) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ using DnsServerCore.Dns.Zones; using System; using System.Collections.Generic; using System.Threading; using TechnitiumLibrary.Net.Dns.ResourceRecords; namespace DnsServerCore.Dns.Trees { class AuthZoneNode : IDisposable { #region variables SubDomainZone _parentSideZone; ApexZone _apexZone; #endregion #region constructors public AuthZoneNode(SubDomainZone parentSideZone, ApexZone zone) { _parentSideZone = parentSideZone; _apexZone = zone; } #endregion #region IDisposable bool _disposed; public void Dispose() { if (_disposed) return; if (_apexZone is not null) _apexZone.Dispose(); _disposed = true; } #endregion #region public public bool TryAdd(ApexZone apexZone) { return Interlocked.CompareExchange(ref _apexZone, apexZone, null) is null; } public bool TryAdd(SubDomainZone parentSideZone) { return Interlocked.CompareExchange(ref _parentSideZone, parentSideZone, null) is null; } public bool TryRemove(out ApexZone apexZone) { apexZone = _apexZone; return ReferenceEquals(Interlocked.CompareExchange(ref _apexZone, null, apexZone), apexZone); } public bool TryRemove(out SubDomainZone parentSideZone) { parentSideZone = _parentSideZone; return ReferenceEquals(Interlocked.CompareExchange(ref _parentSideZone, null, parentSideZone), parentSideZone); } public SubDomainZone GetOrAddParentSideZone(Func valueFactory) { SubDomainZone newParentSideZone = null; while (true) { SubDomainZone parentSideZone = _parentSideZone; if (parentSideZone is not null) return parentSideZone; if (newParentSideZone is null) newParentSideZone = valueFactory(); if (TryAdd(newParentSideZone)) return newParentSideZone; } } public IReadOnlyList QueryRecords(DnsResourceRecordType type, bool dnssecOk) { if ((_apexZone is null) || (type == DnsResourceRecordType.DS)) { if (_parentSideZone is null) return Array.Empty(); return _parentSideZone.QueryRecords(type, dnssecOk); } return _apexZone.QueryRecords(type, dnssecOk); } public AuthZone GetAuthZone(string zoneName) { if ((_apexZone is not null) && _apexZone.Name.Equals(zoneName, StringComparison.OrdinalIgnoreCase)) return _apexZone; return _parentSideZone; } #endregion #region properties public string Name { get { if (_parentSideZone is not null) return _parentSideZone.Name; if (_apexZone is not null) return _apexZone.Name; return null; } } public SubDomainZone ParentSideZone { get { return _parentSideZone; } } public ApexZone ApexZone { get { return _apexZone; } } public bool IsActive { get { if (_apexZone is not null) return _apexZone.IsActive; if (_parentSideZone is not null) return _parentSideZone.IsActive; return false; } } #endregion } }