public async Task ResolveService_WithCnameRef() { var ns = new NameServer(IPAddress.Loopback, 8600); var serviceName = "myservice"; var baseName = "service.consul"; var fullQuery = $"{serviceName}.{baseName}"; ushort prio = 99; ushort weight = 69; ushort port = 88; var response = new DnsResponseMessage(new DnsResponseHeader(1234, (int)DnsResponseCode.NoError, 0, 0, 0, 0), 0); response.AddAnswer( new SrvRecord( new ResourceRecordInfo(fullQuery, ResourceRecordType.SRV, QueryClass.IN, 1000, 0), prio, weight, port, DnsString.Parse(serviceName))); var targetHost = DnsString.Parse("myservice.localhost.net"); response.AddAdditional( new CNameRecord( new ResourceRecordInfo(serviceName, ResourceRecordType.CNAME, QueryClass.IN, 1000, 0), targetHost)); var client = new LookupClient(ns); var mock = new Mock <IDnsQuery>(); mock.Setup(p => p.QueryAsync(It.IsAny <string>(), It.IsAny <QueryType>(), It.IsAny <QueryClass>(), It.IsAny <CancellationToken>())) .Returns(() => Task.FromResult <IDnsQueryResponse>(response.AsQueryResponse(ns, client.Settings))); var mockClient = mock.Object; var result = await mockClient.ResolveServiceAsync(baseName, serviceName); Assert.Single(result); var first = result.First(); Assert.Equal(targetHost.ToString(), first.HostName); Assert.Equal((int)port, first.Port); Assert.Equal((int)prio, first.Priority); Assert.Equal((int)weight, first.Weight); }
public void Cache_GetOrAdd() { var cache = new ResponseCache(true); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out double?effectiveTtl); Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.Equal(100 * 1000, effectiveTtl); }
public void 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 response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any), null)); var item = cache.Get("key", out double?effectiveTtl); Assert.NotNull(item); Assert.Equal(0, item.Answers.First().TimeToLive); Assert.Equal(minTtl, effectiveTtl); }
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 void Cache_GetOrAddExists() { var cache = new ResponseCache(true); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0); response.AddAnswer(record); var success = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.True(success); response.AddAnswer(new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100))); var fail = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.False(fail); }
public void Cache_SupportsInfinite() { var cache = new ResponseCache(true, Timeout.InfiniteTimeSpan); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out double?effectiveTtl); // should not be null although TTL is zero, mimimum timeout is set to infinite Assert.Equal(item, response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.Equal(int.MaxValue, effectiveTtl); }
public void Cache_DoesNotCacheIfDisabled() { var cache = new ResponseCache(false); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out double?effectiveTtl); // should be null because cache is disabled and we create null in the second call of GetOrAdd Assert.Null(item); Assert.Null(effectiveTtl); }
public void Cache_EntriesLowestTTLWins() { var cache = new ResponseCache(true); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1000, 100)); var recordB = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)); var recordC = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0); response.AddAnswer(record); response.AddAdditional(recordB); response.AddAuthority(recordC); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key"); // should be null because recordC has zero TTL which wins Assert.Null(item); }
public void Cache_DoesNotCacheIfZeroTTL() { var cache = new ResponseCache(true); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 0, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out double?effectiveTtl); // should be null because ttl of the record is 0 which disables caching for this record Assert.Null(item); Assert.Null(effectiveTtl); }
public void Cache_RespectsMaximumTtl() { var maxTtl = 2000; var cache = new ResponseCache(true, maximumTimeout: TimeSpan.FromMilliseconds(maxTtl)); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 60 * 60 * 24, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0); response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any), null)); var item = cache.Get("key", out double?effectiveTtl); Assert.NotNull(item); Assert.Equal(1, cache.Count); Assert.Equal(60 * 60 * 24, item.Answers.First().TimeToLive); Assert.Equal(maxTtl, effectiveTtl); }
public void Cache_GetOrAddExists() { var cache = new ResponseCache(); var record = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); var success = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.True(success); response.AddAnswer(new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100))); var fail = cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); Assert.False(fail); }
private async void HandleRequest(byte[] data, IPEndPoint remote) { DnsRequestMessage request = null; try { request = DnsRequestMessage.FromArray(data); OnEvent(OnRequested, new RequestedEventArgs(request, data, remote)); IResponse response = await _coder.Code(request); OnEvent(OnResponded, new RespondedEventArgs(request, response, data, remote)); await _udp.SendAsync(response.ToArray(), response.Size, remote).WithCancellationTimeout(TimeSpan.FromMilliseconds(UDP_TIMEOUT)); } catch (SocketException e) { OnError(e); } catch (ArgumentException e) { OnError(e); } catch (IndexOutOfRangeException e) { OnError(e); } catch (OperationCanceledException e) { OnError(e); } catch (IOException e) { OnError(e); } catch (ObjectDisposedException e) { OnError(e); } catch (Model.ResponseException e) { IResponse response = e.Response; if (response == null) { response = DnsResponseMessage.FromRequest(request); } try { await _udp.SendAsync(response.ToArray(), response.Size, remote).WithCancellationTimeout(TimeSpan.FromMilliseconds(UDP_TIMEOUT)); } catch (SocketException) { } catch (OperationCanceledException) { } finally { OnError(e); } } }
private async void HandleRequest(string sessionID, byte[] data) { DnsRequestMessage request = null; try { request = DnsRequestMessage.FromArray(data); OnEvent(OnRequested, new RequestedEventArgs(request, data)); IResponse response = await _coder.Code(request); OnEvent(OnResponded, new RespondedEventArgs(request, response, data)); _udpServer.SendAsync(sessionID, response.ToArray()); } catch (SocketException e) { OnError(e); } catch (ArgumentException e) { OnError(e); } catch (IndexOutOfRangeException e) { OnError(e); } catch (OperationCanceledException e) { OnError(e); } catch (IOException e) { OnError(e); } catch (ObjectDisposedException e) { OnError(e); } catch (ResponseException e) { IResponse response = e.Response; if (response == null) { response = DnsResponseMessage.FromRequest(request); } try { _udpServer.SendAsync(sessionID, response.ToArray()); } catch (SocketException) { } catch (OperationCanceledException) { } finally { OnError(e); } } }
public void Cache_EntriesLowestTTLWins() { var cache = new ResponseCache(); var record = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 1000, 100)); var recordB = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 100, 100)); var recordC = new EmptyRecord(new ResourceRecord(DnsString.Parse("a"), ARecord.ResourceRecordType, QueryClass.In, 0, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); response.AddAdditional(recordB); response.AddAuthority(recordC); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key", out var effectiveTtl); // should be null because recordC has zero TTL which wins Assert.Null(item); Assert.Null(effectiveTtl); }
public void Resolve_overload_with_IPEndpoint_and_DnsRequetMessage_should_throw_DnsResponseException_when_header_ids_dont_match() { // Arrange. const string domainNameToResolve = "www.A-Dummy-Domain.com"; string domainNameToResolveRoot = domainNameToResolve + "."; const ushort headerId = 123; // because we are *only* setting this up in the request header, it should not match with the response header. DnsRequestHeader header = new DnsRequestHeader(headerId, true, DnsOpCode.Query); DnsQuestion question = new DnsQuestion(mockDnsString.Object, QueryType.A, QueryClass.IN); DnsRequestMessage dnsRequestMessage = new DnsRequestMessage(header, question); IPEndPoint dnsServerIP = new IPEndPoint(IPAddress.Parse("10.0.0.10"), dnsPort53); mockDnsString.Setup(m => m.Value).Returns(domainNameToResolveRoot); DnsResponseMessage responseMessage = GetDnsResponseMessage(); mockMessageProcessor.Setup(m => m.ProcessResponse(It.IsAny <ArraySegment <byte> >())).Returns(responseMessage); IDnsResolver resolver = new DnsResolver(mockCommunicator.Object, mockMessageProcessor.Object); // Act => Act. Assert.Throws <DnsResponseException>(() => resolver.Resolve(dnsServerIP, dnsRequestMessage), "Header id mismatch."); }
public async Task Cache_EntriesLowestTT_Expires() { var cache = new ResponseCache(true); var record = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1000, 100)); var recordB = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 100, 100)); var recordC = new EmptyRecord(new ResourceRecordInfo("a", ResourceRecordType.A, QueryClass.IN, 1, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0); response.AddAnswer(record); response.AddAdditional(recordB); response.AddAuthority(recordC); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); var item = cache.Get("key"); Assert.NotNull(item); await Task.Delay(1100); var item3 = cache.Get("key"); Assert.Null(item3); }
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, 1, 100)); var response = new DnsResponseMessage(new DnsResponseHeader(1, 256, 1, 1, 0, 0), 0) { Audit = new LookupClientAudit() }; response.AddAnswer(record); cache.Add("key", response.AsQueryResponse(new NameServer(IPAddress.Any))); 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 zero because the initial TTL is 100 Assert.Equal(0, item.Answers.First().TimeToLive); Assert.Equal(minTtl, effectiveTtl); }
public static DnsClientResponse FromArray(IRequest request, byte[] message) { DnsResponseMessage response = DnsResponseMessage.FromArray(message); return(new DnsClientResponse(request, response, message)); }
public void ProcessResponse_should_return_DnsResponseMessage_object_with_2_answers_1_question_only_successfully() { // Arrange. const string domainNameToResolve = "www.microsoft.com"; const string domainNameToResolveRoot = domainNameToResolve + "."; const string ipAddress = "10.1.1.100"; const string ipAddress1 = "101.0.0.101"; const ushort headerId = 1001; IDnsString dnsString = new DnsString(domainNameToResolve, domainNameToResolveRoot); ArraySegment <byte> responseData = GetSampleData(ResponseDataSampleFile.QuestionAndAnswerQuery); mockReader.SetupSequence(m => m.ReadUInt16NetworkOrder(responseData)) .Returns(headerId) // id .Returns(33152) // flags .Returns(1) // questionCount .Returns(2) // answerCount .Returns(0) // nameServerCount - setting it to zero for this unit test .Returns(0) // additionCount .Returns(1) // QueryType .Returns(1) // QueryClass // BaseResourceRecordInfo - answer 1 .Returns(1) // record type .Returns(1) // query class .Returns(4) // RDLength // BaseResourceRecordInfo - answer 2 .Returns(1) // record type .Returns(1) //query class .Returns(4); //// RDLength mockReader.Setup(m => m.ReadUInt32NetworkOrder(responseData)).Returns(12); // ttl - 32bit!! // question mockReader.SetupSequence(m => m.ReadQuestionQueryString(responseData)) .Returns(dnsString) // question .Returns(dnsString) // ReadRecordInfo for answer 1 .Returns(dnsString); // ReadRecordInfo for answer 2 mockReader.SetupSequence(m => m.ReadIPAddress(responseData)) .Returns(IPAddress.Parse(ipAddress)) // answer 1 .Returns(IPAddress.Parse(ipAddress1)); // answer 2 mockReader.SetupSequence(m => m.Index) .Returns(8).Returns(12) // answer 1 .Returns(8).Returns(12); // answer 2 INetworkMessageProcessor messageProcessor = new DnsQueryMessageProcessor(mockReader.Object, mockDnsString.Object); // Act. DnsResponseMessage response = messageProcessor.ProcessResponse(responseData); // Assert. Assert.AreEqual(2, response.Answers.Count); Assert.AreEqual(1, response.Questions.Count); Assert.AreEqual(0, response.Additionals.Count); Assert.AreEqual(0, response.Authorities.Count); Assert.AreEqual(headerId, response.Header.Identifier); Assert.IsInstanceOf <ARecord>(response.Answers[0]); // first answer record. Assert.IsInstanceOf <ARecord>(response.Answers[1]); // second answer record. // second Answer check ARecord arecord = response.Answers[1] as ARecord; Assert.AreEqual(domainNameToResolveRoot, response.Answers[1].DomainName.Value); Assert.AreEqual(ipAddress1, arecord.Address.ToString()); // question check Assert.AreEqual(QueryClass.IN, response.Questions[0].QuestionClass); Assert.AreEqual(QueryType.A, response.Questions[0].QuestionType); Assert.AreEqual(domainNameToResolveRoot, response.Questions[0].QueryName.Value); }