Skip to content

Commit

Permalink
Calculated ttl rework. Updated unit tests after PR merge #30
Browse files Browse the repository at this point in the history
Reorganized testing zone files
  • Loading branch information
MichaCo committed Aug 15, 2018
1 parent fc057d5 commit 316ad66
Show file tree
Hide file tree
Showing 11 changed files with 840 additions and 883 deletions.
2 changes: 1 addition & 1 deletion src/DnsClient/DnsMessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
writer.WriteHostName("");
writer.WriteUInt16NetworkOrder((ushort)opt.RecordType);
writer.WriteUInt16NetworkOrder((ushort)opt.RecordClass);
writer.WriteUInt32NetworkOrder((ushort)opt.TimeToLive);
writer.WriteUInt32NetworkOrder((ushort)opt.InitialTimeToLive);
writer.WriteUInt16NetworkOrder(0);
}

Expand Down
2 changes: 1 addition & 1 deletion src/DnsClient/DnsRecordFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private DnsResourceRecord ResolveUriRecord(ResourceRecordInfo info)

private DnsResourceRecord ResolveOptRecord(ResourceRecordInfo info)
{
return new OptRecord((int)info.RecordClass, info.TimeToLive, info.RawDataLength);
return new OptRecord((int)info.RecordClass, info.InitialTimeToLive, info.RawDataLength);
}

private DnsResourceRecord ResolveWksRecord(ResourceRecordInfo info)
Expand Down
35 changes: 25 additions & 10 deletions src/DnsClient/Protocol/DnsResourceRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public DnsResourceRecord(ResourceRecordInfo info)
info?.DomainName ?? throw new ArgumentNullException(nameof(info)),
info?.RecordType ?? throw new ArgumentNullException(nameof(info)),
info?.RecordClass ?? throw new ArgumentNullException(nameof(info)),
info?.TimeToLive ?? throw new ArgumentNullException(nameof(info)),
info?.InitialTimeToLive ?? throw new ArgumentNullException(nameof(info)),
info?.RawDataLength ?? throw new ArgumentNullException(nameof(info)))
{
}
Expand Down Expand Up @@ -46,12 +46,6 @@ public virtual string ToString(int offset = 0)
RecordToString());
}

/// <inheritdoc />
public DnsResourceRecord Clone()
{
return (DnsResourceRecord)MemberwiseClone();
}

/// <summary>
/// Returns a string representation of the record's value only.
/// <see cref="ToString(int)"/> uses this to compose the full string value of this instance.
Expand All @@ -65,6 +59,8 @@ public DnsResourceRecord Clone()
/// </summary>
public class ResourceRecordInfo
{
private readonly int _ticks;

/// <summary>
/// The domain name used to query.
/// </summary>
Expand All @@ -81,9 +77,27 @@ public class ResourceRecordInfo
public QueryClass RecordClass { get; }

/// <summary>
/// The TTL value for the record set by the server.
/// Gets the current time to live value for the record.
/// </summary>
public int TimeToLive
{
get
{
var curTicks = Environment.TickCount & int.MaxValue;
if (curTicks < _ticks)
{
return 0;
}

var ttl = InitialTimeToLive - ((curTicks - _ticks) / 1000);
return ttl < 0 ? 0 : ttl;
}
}

/// <summary>
/// Gets or sets the original time to live returned from the server.
/// </summary>
public int TimeToLive { get; internal set; }
public int InitialTimeToLive { get; internal set; }

/// <summary>
/// Gets the number of bytes for this resource record stored in RDATA
Expand Down Expand Up @@ -118,8 +132,9 @@ public ResourceRecordInfo(DnsString domainName, ResourceRecordType recordType, Q
DomainName = domainName ?? throw new ArgumentNullException(nameof(domainName));
RecordType = recordType;
RecordClass = recordClass;
TimeToLive = timeToLive;
RawDataLength = rawDataLength;
InitialTimeToLive = timeToLive;
_ticks = Environment.TickCount;
}
}
}
18 changes: 9 additions & 9 deletions src/DnsClient/Protocol/Options/OptRecord.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ public DnsResponseCode ResponseCodeEx
{
get
{
return (DnsResponseCode)((TimeToLive & ResponseCodeMask) >> ResponseCodeShift);
return (DnsResponseCode)((InitialTimeToLive & ResponseCodeMask) >> ResponseCodeShift);
}
set
{
TimeToLive &= (int)~ResponseCodeMask;
TimeToLive |= (int)(((int)value << ResponseCodeShift) & ResponseCodeMask);
InitialTimeToLive &= (int)~ResponseCodeMask;
InitialTimeToLive |= (int)(((int)value << ResponseCodeShift) & ResponseCodeMask);
}
}

Expand All @@ -94,27 +94,27 @@ public byte Version
{
get
{
return (byte)((TimeToLive & VersionMask) >> VersionShift);
return (byte)((InitialTimeToLive & VersionMask) >> VersionShift);
}
set
{
TimeToLive = (int)((uint)TimeToLive & ~VersionMask);
TimeToLive |= (int)((value << VersionShift) & VersionMask);
InitialTimeToLive = (int)((uint)InitialTimeToLive & ~VersionMask);
InitialTimeToLive |= (int)((value << VersionShift) & VersionMask);
}
}

public bool IsDnsSecOk
{
get { return (TimeToLive & 0x8000) != 0; }
get { return (InitialTimeToLive & 0x8000) != 0; }
set
{
if (value)
{
TimeToLive |= 0x8000;
InitialTimeToLive |= 0x8000;
}
else
{
TimeToLive &= 0x7fff;
InitialTimeToLive &= 0x7fff;
}
}
}
Expand Down
69 changes: 4 additions & 65 deletions src/DnsClient/ResponseCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public IDnsQueryResponse Get(string key, out double? effectiveTtl)
else
{
StartCleanup();
return entry.GetResponse();
return entry.Response;
}
}

Expand All @@ -97,7 +97,7 @@ public bool Add(string key, IDnsQueryResponse response)
if (all.Any())
{
// in millis
double minTtl = all.Min(p => p.TimeToLive) * 1000d;
double minTtl = all.Min(p => p.InitialTimeToLive) * 1000d;

if (MinimumTimout == Timeout.InfiniteTimeSpan)
{
Expand Down Expand Up @@ -171,8 +171,6 @@ private void StartCleanup()

private class ResponseEntry
{
private readonly IDnsQueryResponse _response;

public bool IsExpiredFor(DateTimeOffset forDate) => forDate >= ExpiresAt;

public DateTimeOffset ExpiresAt { get; }
Expand All @@ -181,73 +179,14 @@ private class ResponseEntry

public double TTL { get; set; }

// returns in seconds, not MS!
public int Elapsed(DateTimeOffset? since = null)
{
if (since == null)
{
since = DateTimeOffset.UtcNow;
}

var elapsedMillis = (int)(since.Value - Created).TotalMilliseconds;
if (elapsedMillis < 0)
{
return 0;
}

return elapsedMillis / 1000;
}

public IDnsQueryResponse GetResponse()
{
var elapsed = Elapsed();
if (elapsed <= 0)
{
return _response;
}

var response = new DnsResponseMessage(_response.Header, _response.MessageSize)
{
Audit = (_response as DnsQueryResponse)?.Audit ?? new LookupClientAudit()
};

foreach (var record in _response.Questions)
{
response.AddQuestion(record);
}

foreach (var record in _response.Answers)
{
var clone = record.Clone();
clone.TimeToLive = clone.TimeToLive - elapsed;
response.AddAnswer(clone);
}

foreach (var record in _response.Additionals)
{
var clone = record.Clone();
clone.TimeToLive = clone.TimeToLive - elapsed;
response.AddAnswer(clone);
}

foreach (var record in _response.Authorities)
{
var clone = record.Clone();
clone.TimeToLive = clone.TimeToLive - elapsed;
response.AddAnswer(clone);
}

var qr = response.AsQueryResponse(_response.NameServer);

return qr;
}
public IDnsQueryResponse Response { get; }

public ResponseEntry(IDnsQueryResponse response, double ttlInMS)
{
Debug.Assert(response != null);
Debug.Assert(ttlInMS >= 0);

_response = response;
Response = response;
TTL = ttlInMS;
Created = DateTimeOffset.UtcNow;
ExpiresAt = Created.AddMilliseconds(TTL);
Expand Down
4 changes: 2 additions & 2 deletions test/DnsClient.Tests/DnsMessageHandlerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void DnsRecordFactory_ResolveARecord()
Assert.Equal(4, resultAnswer.RawDataLength);
Assert.Equal(QueryClass.IN, resultAnswer.RecordClass);
Assert.Equal(ResourceRecordType.A, resultAnswer.RecordType);
Assert.True(resultAnswer.TimeToLive == 100);
Assert.True(resultAnswer.InitialTimeToLive == 100);
Assert.True(result.Header.Id == 42);
Assert.True(result.Header.AnswerCount == 1);
}
Expand All @@ -60,7 +60,7 @@ private static byte[] GetResponseBytes(DnsQueryResponse message, byte[] answerDa
writer.WriteHostName(answer.DomainName.Value);
writer.WriteUInt16NetworkOrder((ushort)answer.RecordType);
writer.WriteUInt16NetworkOrder((ushort)answer.RecordClass);
writer.WriteUInt32NetworkOrder((uint)answer.TimeToLive);
writer.WriteUInt32NetworkOrder((uint)answer.InitialTimeToLive);
writer.WriteUInt16NetworkOrder((ushort)answerData.Length);

//writer.Extend(answerData.Length); // the following data->length
Expand Down
87 changes: 18 additions & 69 deletions test/DnsClient.Tests/DnsResponseParsingTest.cs

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions test/DnsClient.Tests/ResponseCacheTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Task Cache_DoesCacheWithMinimumDefined()
{
var minTtl = 2000;
var cache = new ResponseCache(true, TimeSpan.FromMilliseconds(minTtl));
var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100));
var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1, 100));
var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0)
{
Audit = new LookupClientAudit()
Expand All @@ -57,12 +57,12 @@ public async Task Cache_DoesCacheWithMinimumDefined()

cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any)));

await Task.Delay(1000);
await Task.Delay(1200);
var item = cache.Get("key", out double? effectiveTtl);

// should not be null although TTL is zero, mimimum timeout is set to 2000ms
// TTL of the record should be negative because the initial TTL is 0
Assert.True(item.Answers.First().TimeToLive < 0);
// TTL of the record should be zero because the initial TTL is 100
Assert.Equal(0, item.Answers.First().TimeToLive);
Assert.Equal(minTtl, effectiveTtl);
}

Expand Down
7 changes: 7 additions & 0 deletions tools/etc/named.conf
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ zone "mcnet.com" IN {
file "db.192.168.178.txt";
allow-transfer {192.168.178.1; localhost;};
};

zone "generated.com" IN {
type master;
file "10.0.x.txt";
allow-transfer {192.168.178.1; localhost;};
};

Loading

0 comments on commit 316ad66

Please sign in to comment.