public void AddRecord(DnsResourceRecord record)
        {
            AuthZone zone = GetOrAddSubDomainZone(record.Name);

            zone.AddRecord(record);

            if (zone is SubDomainZone)
            {
                (zone as SubDomainZone).AutoUpdateState();
            }
        }
        public void AddRecord(string domain, DnsResourceRecordType type, uint ttl, DnsResourceRecordData record)
        {
            AuthZone zone = GetOrAddSubDomainZone(domain);

            zone.AddRecord(new DnsResourceRecord(zone.Name, type, DnsClass.IN, ttl, record));

            if (zone is SubDomainZone)
            {
                (zone as SubDomainZone).AutoUpdateState();
            }
        }
        public void UpdateRecord(DnsResourceRecord oldRecord, DnsResourceRecord newRecord)
        {
            if (oldRecord.Type != newRecord.Type)
            {
                throw new DnsServerException("Cannot update record: new record must be of same type.");
            }

            if (oldRecord.Type == DnsResourceRecordType.SOA)
            {
                throw new DnsServerException("Cannot update record: use SetRecords() for updating SOA record.");
            }

            if (!_root.TryGet(oldRecord.Name, out AuthZone zone))
            {
                throw new DnsServerException("Cannot update record: zone does not exists.");
            }

            switch (oldRecord.Type)
            {
            case DnsResourceRecordType.CNAME:
            case DnsResourceRecordType.PTR:
            case DnsResourceRecordType.APP:
                if (oldRecord.Name.Equals(newRecord.Name, StringComparison.OrdinalIgnoreCase))
                {
                    zone.SetRecords(newRecord.Type, new DnsResourceRecord[] { newRecord });

                    if (zone is SubDomainZone)
                    {
                        (zone as SubDomainZone).AutoUpdateState();
                    }
                }
                else
                {
                    zone.DeleteRecords(oldRecord.Type);

                    if (zone is SubDomainZone)
                    {
                        if (zone.IsEmpty)
                        {
                            _root.TryRemove(oldRecord.Name, out _);     //remove empty sub zone
                        }
                        else
                        {
                            (zone as SubDomainZone).AutoUpdateState();
                        }
                    }

                    AuthZone newZone = GetOrAddSubDomainZone(newRecord.Name);

                    newZone.SetRecords(newRecord.Type, new DnsResourceRecord[] { newRecord });

                    if (newZone is SubDomainZone)
                    {
                        (newZone as SubDomainZone).AutoUpdateState();
                    }
                }
                break;

            default:
                if (oldRecord.Name.Equals(newRecord.Name, StringComparison.OrdinalIgnoreCase))
                {
                    zone.DeleteRecord(oldRecord.Type, oldRecord.RDATA);
                    zone.AddRecord(newRecord);

                    if (zone is SubDomainZone)
                    {
                        (zone as SubDomainZone).AutoUpdateState();
                    }
                }
                else
                {
                    zone.DeleteRecord(oldRecord.Type, oldRecord.RDATA);

                    if (zone is SubDomainZone)
                    {
                        if (zone.IsEmpty)
                        {
                            _root.TryRemove(oldRecord.Name, out _);     //remove empty sub zone
                        }
                        else
                        {
                            (zone as SubDomainZone).AutoUpdateState();
                        }
                    }

                    AuthZone newZone = GetOrAddSubDomainZone(newRecord.Name);

                    newZone.AddRecord(newRecord);

                    if (newZone is SubDomainZone)
                    {
                        (newZone as SubDomainZone).AutoUpdateState();
                    }
                }
                break;
            }
        }