Skip to content

Commit

Permalink
Implement Record HashCode and Wire Writing
Browse files Browse the repository at this point in the history
  • Loading branch information
jdomnitz committed Aug 14, 2024
1 parent b1ada88 commit ac6d2ea
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 9 deletions.
13 changes: 12 additions & 1 deletion TinyDNS/Records/AAAARecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ public AAAARecord(ResourceRecordHeader header, string rdata) : base(header)
Address = IPAddress.Parse(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), 16);
pos += 2;
Address.TryWriteBytes(buffer.Slice(pos, 16), out _);
pos += 16;
}

public override bool Equals(ResourceRecord? other)
{
if (other is AAAARecord otherAAAA)
Expand All @@ -47,7 +56,9 @@ public override bool Equals(ResourceRecord? other)

public override int GetHashCode()
{
return Address.GetHashCode() + (int)Type;
HashCode hc = GetBaseHash();
hc.Add(Address);
return hc.ToHashCode();
}

public override string ToString()
Expand Down
13 changes: 12 additions & 1 deletion TinyDNS/Records/ARecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ public ARecord(ResourceRecordHeader header, string rdata) : base(header)
Address = IPAddress.Parse(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), 4);
pos += 2;
Address.TryWriteBytes(buffer.Slice(pos, 4), out _);
pos += 4;
}

public override bool Equals(ResourceRecord? other)
{
if (other is ARecord otherA)
Expand All @@ -47,7 +56,9 @@ public override bool Equals(ResourceRecord? other)

public override int GetHashCode()
{
return Address.GetHashCode() + (int)Type;
HashCode hc = GetBaseHash();
hc.Add(Address);
return hc.ToHashCode();
}

public override string ToString()
Expand Down
19 changes: 19 additions & 0 deletions TinyDNS/Records/CNameRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using TinyDNS.Enums;

namespace TinyDNS.Records
Expand All @@ -35,13 +37,30 @@ public CNameRecord(ResourceRecordHeader header, string rdata) : base(header)
CNameLabels = DomainParser.Parse(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
pos += 2;
int start = pos;
DomainParser.Write(CNameLabels, buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(start - 2, 2), (ushort)(pos- start));
}

public override bool Equals(ResourceRecord? other)
{
if (other is CNameRecord otherCName)
return base.Equals(other) && CNameLabels.SequenceEqual(otherCName.CNameLabels);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
foreach (string label in CNameLabels)
hc.Add(label);
return hc.ToHashCode();
}

public override string ToString()
{
return base.ToString() + $"\t{CName}";
Expand Down
19 changes: 19 additions & 0 deletions TinyDNS/Records/DNameRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using TinyDNS.Enums;

namespace TinyDNS.Records
Expand All @@ -35,13 +37,30 @@ public DNameRecord(ResourceRecordHeader header, string rdata) : base(header)
DNameLabels = DomainParser.Parse(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
pos += 2;
int start = pos;
DomainParser.Write(DNameLabels, buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(start - 2, 2), (ushort)(pos- start));
}

public override bool Equals(ResourceRecord? other)
{
if (other is DNameRecord otherDName)
return base.Equals(other) && DNameLabels.SequenceEqual(otherDName.DNameLabels);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
foreach (string label in DNameLabels)
hc.Add(label);
return hc.ToHashCode();
}

public override string ToString()
{
return base.ToString() + $"\t{DName}";
Expand Down
20 changes: 20 additions & 0 deletions TinyDNS/Records/PtrRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using TinyDNS.Enums;

namespace TinyDNS.Records
Expand All @@ -35,13 +37,31 @@ public PtrRecord(ResourceRecordHeader header, string rdata) : base(header)
DomainLabels = DomainParser.Parse(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
pos += 2;
int start = pos;
DomainParser.Write(DomainLabels, buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(start - 2, 2), (ushort)(pos- start));
}

public override bool Equals(ResourceRecord? other)
{
if (other is PtrRecord otherPtr)
return base.Equals(other) && DomainLabels.SequenceEqual(otherPtr.DomainLabels);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
foreach (var label in DomainLabels)
hc.Add(label);
int code = hc.ToHashCode();
return code;
}

public override string ToString()
{
return base.ToString() + $"\t{Domain}";
Expand Down
28 changes: 26 additions & 2 deletions TinyDNS/Records/ResourceRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class ResourceRecord : IEquatable<ResourceRecord>
public DNSClass Class { get { return header.Class; } set { header.Class = value; } }
public DNSRecordType Type { get { return header.Type; } set { header.Type = value; } }
public List<string> Labels { get { return header.Labels; } set { header.Labels = value; } }
public DateTime Created { get { return header.Created; } set { header.Created = value; } }
public DateTime Expires { get { return header.Expires; } set { header.Expires = value; } }
public bool CacheFlush { get { return header.CacheFlush; } set { header.CacheFlush = value; } }
public string Name { get { return string.Join('.', header.Labels); } }
Expand Down Expand Up @@ -78,14 +79,37 @@ public static ResourceRecord Parse(Span<byte> buffer, ref int pos)
return record;
}

public void Write(Span<byte> buffer, ref int pos)
public virtual void Write(Span<byte> buffer, ref int pos)
{
header.Write(buffer, ref pos);
}

public override bool Equals(object? obj)
{
if (obj is ResourceRecord record)
return Equals(record);
return false;
}

public virtual bool Equals(ResourceRecord? other)
{
return Type == other!.Type && Name.SequenceEqual(other!.Name);
if (other == null)
return false;
return Type == other!.Type && Labels.SequenceEqual(other!.Labels);
}

protected HashCode GetBaseHash()
{
HashCode hc = new HashCode();
hc.Add(Type);
foreach (var label in Labels)
hc.Add(label);
return hc;
}

public override int GetHashCode()
{
return GetBaseHash().ToHashCode();
}

internal static ResourceRecord Parse(string line)
Expand Down
14 changes: 11 additions & 3 deletions TinyDNS/Records/ResourceRecordHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class ResourceRecordHeader
public DNSRecordType Type { get; set; }
public List<string> Labels { get; set; }
public DateTime Expires { get; set; }
public DateTime Created { get; set; }
public bool CacheFlush { get; set; }

public ResourceRecordHeader(Span<byte> buffer, ref int pos)
Expand All @@ -32,7 +33,8 @@ public ResourceRecordHeader(Span<byte> buffer, ref int pos)
pos += 2;
CacheFlush = (recordClass & 0x8000) == 0x8000;
Class = (DNSClass)(recordClass & 0x7FFF);
Expires = DateTime.Now + TimeSpan.FromSeconds(BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(pos, 4)));
Created = DateTime.Now;
Expires = Created + TimeSpan.FromSeconds(BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(pos, 4)));
pos += 4;
}

Expand All @@ -42,15 +44,17 @@ public ResourceRecordHeader(string[] columns)
Type = DNSRecordParser.Parse(columns[2]);
uint ttl = uint.Parse(columns[1]);
Class = DNSClass.IN;
Expires = DateTime.Now + TimeSpan.FromSeconds(ttl);
Created = DateTime.Now;
Expires = Created + TimeSpan.FromSeconds(ttl);
}

public ResourceRecordHeader(List<string> labels, DNSRecordType type, DNSClass @class, uint ttl)
{
this.Labels = labels;
this.Type = type;
this.Class = @class;
this.Expires = DateTime.Now + TimeSpan.FromSeconds(ttl);
Created = DateTime.Now;
Expires = Created + TimeSpan.FromSeconds(ttl);
}

public void Write(Span<byte> buffer, ref int pos)
Expand All @@ -62,6 +66,10 @@ public void Write(Span<byte> buffer, ref int pos)
if (CacheFlush)
ClassVal |= 0x8000;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), ClassVal);
pos += 2;
uint ttl = (uint)(Expires - DateTime.Now).TotalSeconds;
BinaryPrimitives.WriteUInt32BigEndian(buffer.Slice(pos, 4), ttl);
pos += 4;
}
}
}
30 changes: 29 additions & 1 deletion TinyDNS/Records/SRVRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using TinyDNS.Enums;

namespace TinyDNS.Records
Expand Down Expand Up @@ -43,13 +44,40 @@ public SRVRecord(string service, ushort priority, ushort port, ushort weight, Li
Weight = weight;
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
//Length
pos += 2;
int start = pos;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), Priority);
pos += 2;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), Weight);
pos += 2;
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), Port);
pos += 2;
DomainParser.Write(TargetLabels, buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(start - 2, 2), (ushort)(pos- start));
}

public override bool Equals(ResourceRecord? other)
{
if (other is SRVRecord otherSrv)
return base.Equals(other) && Port == otherSrv.Port && TargetLabels.Equals(otherSrv.TargetLabels);
return base.Equals(other) && Port == otherSrv.Port && TargetLabels.SequenceEqual(otherSrv.TargetLabels);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
hc.Add(Port);
hc.Add(Priority);
hc.Add(Weight);
foreach (string label in TargetLabels)
hc.Add(label);
return hc.ToHashCode();
}

public override string ToString()
{
return base.ToString() + $"\t{Priority}\t{Weight}\t{Port}\t{Target}";
Expand Down
17 changes: 16 additions & 1 deletion TinyDNS/Records/TxtRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using System.Text;
using TinyDNS.Enums;

Expand Down Expand Up @@ -46,13 +47,27 @@ public TxtRecord(List<string> strings, List<string> labels, DNSClass @class, uin
Strings = strings;
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
//TODO
}

public override bool Equals(ResourceRecord? other)
{
if (other is TxtRecord otherTxt)
return base.Equals(other) && Strings.Equals(otherTxt.Strings);
return base.Equals(other) && Strings.SequenceEqual(otherTxt.Strings);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
foreach (string txtString in Strings)
hc.Add(txtString);
return hc.ToHashCode();
}

public override string ToString()
{
return base.ToString() + $"\t{string.Join(',', Strings)}";
Expand Down
17 changes: 17 additions & 0 deletions TinyDNS/Records/UnsupportedRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.

using System.Buffers.Binary;
using System.Net;
using System.Text;
using TinyDNS.Enums;

Expand Down Expand Up @@ -42,13 +43,29 @@ public UnsupportedRecord(ResourceRecordHeader header, string rdata) : base(heade
RData = Encoding.UTF8.GetBytes(rdata);
}

public override void Write(Span<byte> buffer, ref int pos)
{
base.Write(buffer, ref pos);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(pos, 2), (ushort)RData.Length);
pos += 2;
RData.CopyTo(buffer.Slice(pos, RData.Length));
pos += RData.Length;
}

public override bool Equals(ResourceRecord? other)
{
if (other is UnsupportedRecord unsupported)
return base.Equals(other) && RData.Equals(unsupported.RData);
return false;
}

public override int GetHashCode()
{
HashCode hc = GetBaseHash();
hc.Add(RData);
return hc.ToHashCode();
}

public override string ToString()
{
return base.ToString() + $"\t{RData.Length} Bytes";
Expand Down

0 comments on commit ac6d2ea

Please sign in to comment.