diff --git a/src/DnsClient/DnsMessageHandler.cs b/src/DnsClient/DnsMessageHandler.cs index 02701212..ffaa9dfb 100644 --- a/src/DnsClient/DnsMessageHandler.cs +++ b/src/DnsClient/DnsMessageHandler.cs @@ -19,7 +19,7 @@ internal enum DnsMessageHandleType TCP } - internal abstract class DnsMessageHandler + internal abstract class DnsMessageHandler : IDisposable { public abstract DnsMessageHandleType Type { get; } @@ -174,5 +174,16 @@ public virtual DnsResponseMessage GetResponseMessage(ArraySegment response return response; } + + protected virtual void Dispose(bool disposing) + { + // Nothing to do in base class. + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } } } diff --git a/src/DnsClient/DnsTcpMessageHandler.cs b/src/DnsClient/DnsTcpMessageHandler.cs index eba19e2e..246ab973 100644 --- a/src/DnsClient/DnsTcpMessageHandler.cs +++ b/src/DnsClient/DnsTcpMessageHandler.cs @@ -15,18 +15,22 @@ namespace DnsClient { internal class DnsTcpMessageHandler : DnsMessageHandler { + private bool _disposedValue = false; private readonly ConcurrentDictionary _pools = new ConcurrentDictionary(); public override DnsMessageHandleType Type { get; } = DnsMessageHandleType.TCP; public override DnsResponseMessage Query(IPEndPoint server, DnsRequestMessage request, TimeSpan timeout) { - CancellationToken cancellationToken = default; + if (_disposedValue) + { + throw new ObjectDisposedException(nameof(DnsTcpMessageHandler)); + } using var cts = timeout.TotalMilliseconds != Timeout.Infinite && timeout.TotalMilliseconds < int.MaxValue ? new CancellationTokenSource(timeout) : null; - cancellationToken = cts?.Token ?? default; + var cancellationToken = cts?.Token ?? default; ClientPool pool; while (!_pools.TryGetValue(server, out pool)) @@ -36,7 +40,7 @@ public override DnsResponseMessage Query(IPEndPoint server, DnsRequestMessage re cancellationToken.ThrowIfCancellationRequested(); - var entry = pool.GetNextClient(); + var entry = pool.GetNextClient(cancellationToken); using var cancelCallback = cancellationToken.Register(() => { @@ -79,6 +83,11 @@ public override async Task QueryAsync( DnsRequestMessage request, CancellationToken cancellationToken) { + if (_disposedValue) + { + throw new ObjectDisposedException(nameof(DnsTcpMessageHandler)); + } + cancellationToken.ThrowIfCancellationRequested(); ClientPool pool; @@ -87,7 +96,7 @@ public override async Task QueryAsync( _pools.TryAdd(server, new ClientPool(true, server)); } - var entry = pool.GetNextClient(); + var entry = await pool.GetNextClientAsync(cancellationToken).ConfigureAwait(false); using var cancelCallback = cancellationToken.Register(() => { @@ -301,9 +310,24 @@ private async Task QueryAsyncInternal(TcpClient client, DnsR return DnsResponseMessage.Combine(responses); } - private class ClientPool : IDisposable + protected override void Dispose(bool disposing) + { + if (disposing && !_disposedValue) + { + _disposedValue = true; + + foreach (var entry in _pools) + { + entry.Value.Dispose(); + } + } + + base.Dispose(disposing); + } + + private sealed class ClientPool : IDisposable { - private bool _disposedValue; + private bool _disposedValue = false; private readonly bool _enablePool; private ConcurrentQueue _clients = new ConcurrentQueue(); private readonly IPEndPoint _endpoint; @@ -314,7 +338,66 @@ public ClientPool(bool enablePool, IPEndPoint endpoint) _endpoint = endpoint; } - public ClientEntry GetNextClient() + public ClientEntry GetNextClient(CancellationToken cancellationToken) + { + if (_disposedValue) + { + throw new ObjectDisposedException(nameof(ClientPool)); + } + + ClientEntry entry = null; + if (_enablePool) + { + while (entry == null && !TryDequeue(out entry)) + { + entry = ConnectNew(cancellationToken); + } + } + else + { + entry = ConnectNew(cancellationToken); + } + + return entry; + } + + private ClientEntry ConnectNew(CancellationToken cancellationToken) + { + var newClient = new TcpClient(_endpoint.AddressFamily) + { + LingerState = new LingerOption(true, 0) + }; + + bool gotCanceled = false; + cancellationToken.Register(() => + { + gotCanceled = true; + newClient.Dispose(); + }); + + try + { + newClient.Connect(_endpoint.Address, _endpoint.Port); + } + catch (Exception) when (gotCanceled) + { + throw new OperationCanceledException("Connection timed out.", cancellationToken); + } + catch (Exception) + { + try + { + newClient.Dispose(); + } + catch { } + + throw; + } + + return new ClientEntry(newClient, _endpoint); + } + + public async Task GetNextClientAsync(CancellationToken cancellationToken) { if (_disposedValue) { @@ -326,17 +409,57 @@ public ClientEntry GetNextClient() { while (entry == null && !TryDequeue(out entry)) { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily) { LingerState = new LingerOption(true, 0) }, _endpoint); + entry = await ConnectNewAsync(cancellationToken).ConfigureAwait(false); } } else { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily), _endpoint); + entry = await ConnectNewAsync(cancellationToken).ConfigureAwait(false); } return entry; } + private async Task ConnectNewAsync(CancellationToken cancellationToken) + { + var newClient = new TcpClient(_endpoint.AddressFamily) + { + LingerState = new LingerOption(true, 0) + }; + +#if NET6_0_OR_GREATER + await newClient.ConnectAsync(_endpoint.Address, _endpoint.Port, cancellationToken).ConfigureAwait(false); +#else + + bool gotCanceled = false; + cancellationToken.Register(() => + { + gotCanceled = true; + newClient.Dispose(); + }); + + try + { + await newClient.ConnectAsync(_endpoint.Address, _endpoint.Port).ConfigureAwait(false); + } + catch (Exception) when (gotCanceled) + { + throw new OperationCanceledException("Connection timed out.", cancellationToken); + } + catch (Exception) + { + try + { + newClient.Dispose(); + } + catch { } + + throw; + } +#endif + return new ClientEntry(newClient, _endpoint); + } + public void Enqueue(ClientEntry entry) { if (_disposedValue) @@ -390,29 +513,20 @@ public bool TryDequeue(out ClientEntry entry) return result; } - protected virtual void Dispose(bool disposing) + public void Dispose() { if (!_disposedValue) { - if (disposing) + _disposedValue = true; + foreach (var entry in _clients) { - foreach (var entry in _clients) - { - entry.DisposeClient(); - } - - _clients = new ConcurrentQueue(); + entry.DisposeClient(); } - _disposedValue = true; + _clients = new ConcurrentQueue(); } } - public void Dispose() - { - Dispose(true); - } - public class ClientEntry { public ClientEntry(TcpClient client, IPEndPoint endpoint) diff --git a/src/DnsClient/LookupClient.cs b/src/DnsClient/LookupClient.cs index 643d956b..562d30b4 100644 --- a/src/DnsClient/LookupClient.cs +++ b/src/DnsClient/LookupClient.cs @@ -40,7 +40,7 @@ namespace DnsClient /// ]]> /// /// - public class LookupClient : ILookupClient, IDnsQuery + public sealed class LookupClient : ILookupClient, IDnsQuery, IDisposable { private const int LogEventStartQuery = 1; private const int LogEventQuery = 2; @@ -66,6 +66,7 @@ public class LookupClient : ILookupClient, IDnsQuery private readonly SkipWorker _skipper; private IReadOnlyCollection _resolvedNameServers; + private bool _disposedValue; /// public IReadOnlyCollection NameServers => Settings.NameServers; @@ -212,7 +213,7 @@ internal LookupClient(LookupClientOptions options, DnsMessageHandler udpHandler // Setting up name servers. // Using manually configured ones and/or auto resolved ones. - IReadOnlyCollection servers = _originalOptions.NameServers?.ToArray() ?? new NameServer[0]; + IReadOnlyCollection servers = _originalOptions.NameServers?.ToArray() ?? Array.Empty(); if (options.AutoResolveNameServers) { @@ -269,7 +270,9 @@ private void CheckResolvedNameservers() } _resolvedNameServers = newServers; - var servers = _originalOptions.NameServers.Concat(_resolvedNameServers).ToArray(); + IReadOnlyCollection servers = _originalOptions.NameServers.Concat(_resolvedNameServers).ToArray(); + servers = NameServer.ValidateNameServers(servers, _logger); + Settings = new LookupClientSettings(_originalOptions, servers); } catch (Exception ex) @@ -1634,6 +1637,17 @@ public void MaybeDoWork() } } } + + /// + public void Dispose() + { + if (!_disposedValue) + { + _disposedValue = true; + _tcpFallbackHandler?.Dispose(); + _messageHandler?.Dispose(); + } + } } internal class LookupClientAudit diff --git a/test-other/OldReference/TestLookupClient.cs b/test-other/OldReference/TestLookupClient.cs index aaa14df2..a9a5f86b 100644 --- a/test-other/OldReference/TestLookupClient.cs +++ b/test-other/OldReference/TestLookupClient.cs @@ -56,7 +56,7 @@ public void TestOtherTypes() public void TestQuery_1_1() { - var client = new LookupClient(); + var client = new LookupClient(NameServer.GooglePublicDns.Address); client.Query("domain", QueryType.A); client.Query("domain", QueryType.A, QueryClass.IN); client.QueryReverse(IPAddress.Loopback); @@ -76,7 +76,7 @@ public void TestQuery_1_1() public async Task TestQueryAsync_1_1() { - var client = new LookupClient(); + var client = new LookupClient(NameServer.GooglePublicDns.Address); await client.QueryAsync("domain", QueryType.A).ConfigureAwait(false); await client.QueryAsync("domain", QueryType.A, QueryClass.IN).ConfigureAwait(false); await client.QueryAsync("domain", QueryType.A, cancellationToken: default).ConfigureAwait(false); diff --git a/test/DnsClient.Tests/LookupTest.cs b/test/DnsClient.Tests/LookupTest.cs index c9d5db87..76ac1682 100644 --- a/test/DnsClient.Tests/LookupTest.cs +++ b/test/DnsClient.Tests/LookupTest.cs @@ -34,7 +34,7 @@ static LookupTest() [Fact] public async Task TestingFor_LeakyMemory() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions() { UseCache = false, @@ -61,7 +61,7 @@ public async Task TestingFor_LeakyMemory() [Fact] public async Task TestingFor_LeakyMemory_Tcp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions() { UseCache = false, @@ -113,7 +113,7 @@ public async Task ResolveService_WithCnameRef() new ResourceRecordInfo(serviceName, ResourceRecordType.CNAME, QueryClass.IN, 1000, 0), targetHost)); - var client = new LookupClient(ns); + using var client = new LookupClient(ns); var mock = new Mock(); mock.Setup(p => p.QueryAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) @@ -152,7 +152,7 @@ public async Task ResolveService_WithFQNSrv() port, targetHost)); - var client = new LookupClient(ns); + using var client = new LookupClient(ns); var mock = new Mock(); mock.Setup(p => p.QueryAsync(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) @@ -201,7 +201,8 @@ public async Task Lookup_Query_SettingsCannotBeNull() [Fact] public async Task Lookup_GetHostAddresses_Local() { - var client = new LookupClient(); + var servers = NameServer.ResolveNameServers(true, false); + using var client = new LookupClient(servers.ToArray()); var result = await client.QueryAsync("localhost", QueryType.A); @@ -215,7 +216,7 @@ public async Task Lookup_GetHostAddresses_Local() [Fact] public void Lookup_GetHostAddresses_Local_Sync() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = client.Query("localhost", QueryType.A); @@ -269,7 +270,7 @@ public void Lookup_LargeResultWithTCP() [Fact] public void Lookup_IPv4_Works() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { // force both requests @@ -289,7 +290,7 @@ public void Lookup_IPv4_Works() [Fact] public void Lookup_IPv4_TcpOnly_Works() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { // force both requests @@ -310,7 +311,7 @@ public void Lookup_IPv4_TcpOnly_Works() [Fact] public void Lookup_IPv6_Works() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDnsIPv6) { // force both requests @@ -330,7 +331,7 @@ public void Lookup_IPv6_Works() [Fact] public void Lookup_IPv6_TcpOnly_Works() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDnsIPv6) { // force both requests @@ -351,7 +352,7 @@ public void Lookup_IPv6_TcpOnly_Works() [Fact] public void Lookup_MultiServer_IPv4_and_IPv6() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns, NameServer.GooglePublicDnsIPv6) { // force both requests @@ -371,7 +372,7 @@ public void Lookup_MultiServer_IPv4_and_IPv6() [Fact] public void Lookup_MultiServer_IPv4_and_IPv6_TCP() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns, NameServer.GooglePublicDnsIPv6) { // force both requests @@ -392,7 +393,7 @@ public void Lookup_MultiServer_IPv4_and_IPv6_TCP() [Fact] public async Task Lookup_ThrowDnsErrors() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true @@ -406,7 +407,7 @@ public async Task Lookup_ThrowDnsErrors() [Fact] public void Lookup_ThrowDnsErrors_Sync() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true @@ -422,7 +423,7 @@ public class QueryTimesOutTests [Fact] public async Task Lookup_QueryTimesOut_Udp_Async() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Timeout = s_timeout, @@ -439,7 +440,7 @@ public async Task Lookup_QueryTimesOut_Udp_Async() [Fact] public void Lookup_QueryTimesOut_Udp_Sync() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Timeout = s_timeout, @@ -456,7 +457,7 @@ public void Lookup_QueryTimesOut_Udp_Sync() [Fact] public async Task Lookup_QueryTimesOut_Tcp_Async() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Timeout = s_timeout, @@ -473,7 +474,7 @@ public async Task Lookup_QueryTimesOut_Tcp_Async() [Fact] public void Lookup_QueryTimesOut_Tcp_Sync() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Timeout = s_timeout, @@ -493,7 +494,7 @@ public class DelayCancelTest [Fact] public async Task Lookup_QueryDelayCanceled_Udp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Retries = 0, @@ -514,7 +515,7 @@ public async Task Lookup_QueryDelayCanceled_Udp() [Fact] public async Task Lookup_QueryDelayCanceled_Tcp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Retries = 0, @@ -534,7 +535,7 @@ public async Task Lookup_QueryDelayCanceled_Tcp() [Fact] public async Task Lookup_QueryDelayCanceledWithUnlimitedTimeout_Udp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Retries = 0, @@ -554,7 +555,7 @@ public async Task Lookup_QueryDelayCanceledWithUnlimitedTimeout_Udp() [Fact] public async Task Lookup_QueryDelayCanceledWithUnlimitedTimeout_Tcp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(s_doesNotExist) { Retries = 0, @@ -575,7 +576,7 @@ public async Task Lookup_QueryDelayCanceledWithUnlimitedTimeout_Tcp() [Fact] public async Task Lookup_QueryCanceled_Udp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { UseTcpFallback = false @@ -594,7 +595,7 @@ public async Task Lookup_QueryCanceled_Udp() [Fact] public async Task Lookup_QueryCanceled_Tcp() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { UseTcpOnly = true @@ -613,7 +614,7 @@ public async Task Lookup_QueryCanceled_Tcp() [Fact] public async Task GetHostName() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); string hostName = await client.GetHostNameAsync(IPAddress.Parse("8.8.8.8")); Assert.Equal("dns.google", hostName); @@ -622,7 +623,7 @@ public async Task GetHostName() [Fact] public async Task Lookup_Reverse() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = await client.QueryReverseAsync(IPAddress.Parse("127.0.0.1")); Assert.Equal("localhost.", result.Answers.PtrRecords().First().PtrDomainName.Value); @@ -631,7 +632,7 @@ public async Task Lookup_Reverse() [Fact] public void Lookup_ReverseSync() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = client.QueryReverse(IPAddress.Parse("127.0.0.1")); Assert.Equal("localhost.", result.Answers.PtrRecords().First().PtrDomainName.Value); @@ -640,7 +641,7 @@ public void Lookup_ReverseSync() [Fact] public async Task Lookup_Query_AAAA() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.AAAA); Assert.NotEmpty(result.Answers.AaaaRecords()); @@ -650,7 +651,7 @@ public async Task Lookup_Query_AAAA() [Fact] public void Lookup_Query_AAAA_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.AAAA); Assert.NotEmpty(result.Answers.AaaaRecords()); @@ -660,7 +661,7 @@ public void Lookup_Query_AAAA_Sync() [Fact] public async Task Lookup_Query_Any() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.ANY); Assert.NotEmpty(result.Answers); @@ -670,7 +671,7 @@ public async Task Lookup_Query_Any() [Fact] public void Lookup_Query_Any_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.ANY); Assert.NotEmpty(result.Answers); @@ -680,7 +681,7 @@ public void Lookup_Query_Any_Sync() [Fact] public async Task Lookup_Query_Mx() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.MX); Assert.NotEmpty(result.Answers.MxRecords()); @@ -691,7 +692,7 @@ public async Task Lookup_Query_Mx() [Fact] public void Lookup_Query_Mx_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.MX); Assert.NotEmpty(result.Answers.MxRecords()); @@ -702,7 +703,7 @@ public void Lookup_Query_Mx_Sync() [Fact] public async Task Lookup_Query_NS() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.NS); Assert.NotEmpty(result.Answers.NsRecords()); @@ -712,7 +713,7 @@ public async Task Lookup_Query_NS() [Fact] public void Lookup_Query_NS_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.NS); Assert.NotEmpty(result.Answers.NsRecords()); @@ -722,7 +723,7 @@ public void Lookup_Query_NS_Sync() [Fact] public async Task Lookup_Query_TXT() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.TXT); Assert.NotEmpty(result.Answers.TxtRecords()); @@ -733,7 +734,7 @@ public async Task Lookup_Query_TXT() [Fact] public void Lookup_Query_TXT_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.TXT); Assert.NotEmpty(result.Answers.TxtRecords()); @@ -744,7 +745,7 @@ public void Lookup_Query_TXT_Sync() [Fact] public async Task Lookup_Query_SOA() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("google.com", QueryType.SOA); Assert.NotEmpty(result.Answers.SoaRecords()); @@ -755,7 +756,7 @@ public async Task Lookup_Query_SOA() [Fact] public void Lookup_Query_SOA_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("google.com", QueryType.SOA); Assert.NotEmpty(result.Answers.SoaRecords()); @@ -766,7 +767,7 @@ public void Lookup_Query_SOA_Sync() [Fact] public async Task Lookup_Query_Puny() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("müsli.de", QueryType.A); Assert.NotEmpty(result.Answers); @@ -776,7 +777,7 @@ public async Task Lookup_Query_Puny() [Fact] public void Lookup_Query_Puny_Sync() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("müsli.de", QueryType.A); Assert.NotEmpty(result.Answers); @@ -786,7 +787,7 @@ public void Lookup_Query_Puny_Sync() [Fact] public void Lookup_Query_Puny2() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.Query("müsli.com", QueryType.ANY); Assert.NotEmpty(result.Answers); @@ -797,7 +798,7 @@ public void Lookup_Query_Puny2() public void Ip_Arpa_v4_Valid() { var ip = IPAddress.Parse("8.8.4.4"); - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = DnsString.Parse(ip.GetArpaName()); var queryResult = client.QueryReverse(ip); @@ -810,7 +811,7 @@ public void Ip_Arpa_v4_Valid() public void Ip_Arpa_v6_Valid() { var ip = NameServer.GooglePublicDns2IPv6.Address; - var client = new LookupClient(NameServer.GooglePublicDnsIPv6); + using var client = new LookupClient(NameServer.GooglePublicDnsIPv6); var result = DnsString.Parse(ip.GetArpaName()); var queryResult = client.QueryReverse(ip); @@ -822,7 +823,7 @@ public void Ip_Arpa_v6_Valid() [Fact] public async Task Lookup_Query_NaPtr() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.QueryAsync("tel.t-online.de", QueryType.NAPTR); Assert.NotEmpty(result.Answers.NAPtrRecords()); @@ -839,7 +840,7 @@ public async Task Lookup_Query_NaPtr() [Fact] public async Task Lookup_Query_CERT() { - var client = new LookupClient(NameServer.Cloudflare); + using var client = new LookupClient(NameServer.Cloudflare); var result = await client.QueryAsync("d1.domain1.dcdt31.healthit.gov", QueryType.CERT); Assert.NotEmpty(result.Answers.CertRecords()); @@ -861,7 +862,7 @@ public async Task Lookup_Query_CERT() [Fact] public async Task GetHostEntry_ExampleSub() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var hostEntry = await client.GetHostEntryAsync("mail.google.com"); //Assert.EndsWith("google.com", hostEntry.Aliases.First(), StringComparison.OrdinalIgnoreCase); Assert.Equal("mail.google.com", hostEntry.HostName); @@ -871,7 +872,7 @@ public async Task GetHostEntry_ExampleSub() [Fact] public void GetHostEntry_ByName_ManyIps_NoAlias() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.GetHostEntry("google.com"); @@ -883,7 +884,7 @@ public void GetHostEntry_ByName_ManyIps_NoAlias() [Fact] public void GetHostEntry_ByName_ManyAliases() { - var client = new LookupClient(new LookupClientOptions(NameServer.GooglePublicDns) + using var client = new LookupClient(new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true }); @@ -898,7 +899,7 @@ public void GetHostEntry_ByName_ManyAliases() [Fact] public void GetHostEntry_ByName_EmptyString() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); void act() => client.GetHostEntry(""); @@ -908,7 +909,7 @@ public void GetHostEntry_ByName_EmptyString() [Fact] public void GetHostEntry_ByName_HostDoesNotExist() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.GetHostEntry("lolhost"); @@ -920,7 +921,7 @@ public void GetHostEntry_ByName_HostDoesNotExist() [Fact] public void GetHostEntry_ByName_HostDoesNotExist_WithThrow() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true @@ -934,7 +935,7 @@ public void GetHostEntry_ByName_HostDoesNotExist_WithThrow() [Fact] public void GetHostEntry_ByIp_NoHost() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = client.GetHostEntry("1.0.0.0"); @@ -944,7 +945,7 @@ public void GetHostEntry_ByIp_NoHost() [Fact] public void GetHostEntry_ByIp_NoHost_WithThrow() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true @@ -958,7 +959,7 @@ public void GetHostEntry_ByIp_NoHost_WithThrow() [Fact] public void GetHostEntry_ByManyIps() { - var client = new LookupClient(new LookupClientOptions(NameServer.GooglePublicDns) + using var client = new LookupClient(new LookupClientOptions(NameServer.GooglePublicDns) { ThrowDnsErrors = true }); @@ -985,7 +986,7 @@ public void GetHostEntry_ByManyIps() [Fact] public async Task GetHostEntryAsync_ByName_ManyIps_NoAlias() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.GetHostEntryAsync("google.com"); @@ -997,7 +998,7 @@ public async Task GetHostEntryAsync_ByName_ManyIps_NoAlias() [Fact] public async Task GetHostEntryAsync_ByName_OneIp_ManyAliases() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var result = await client.GetHostEntryAsync("dnsclient.michaco.net"); @@ -1009,7 +1010,7 @@ public async Task GetHostEntryAsync_ByName_OneIp_ManyAliases() [Fact] public async Task GetHostEntryAsync_ByName_OneIp_NoAlias() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = await client.GetHostEntryAsync("localhost"); @@ -1021,7 +1022,7 @@ public async Task GetHostEntryAsync_ByName_OneIp_NoAlias() [Fact] public async Task GetHostEntryAsync_ByName_HostDoesNotExist_WithThrow() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions() { ThrowDnsErrors = true @@ -1035,7 +1036,7 @@ public async Task GetHostEntryAsync_ByName_HostDoesNotExist_WithThrow() [Fact] public async Task GetHostEntryAsync_ByName_EmptyString() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); await Assert.ThrowsAsync("hostNameOrAddress", () => client.GetHostEntryAsync("")); } @@ -1043,7 +1044,7 @@ public async Task GetHostEntryAsync_ByName_EmptyString() [Fact] public async Task GetHostEntryAsync_ByName_HostDoesNotExist() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = await client.GetHostEntryAsync("lolhost"); @@ -1055,7 +1056,7 @@ public async Task GetHostEntryAsync_ByName_HostDoesNotExist() [Fact] public async Task GetHostEntryAsync_ByIp_NoHost() { - var client = new LookupClient(); + using var client = new LookupClient(); var result = await client.GetHostEntryAsync("1.0.0.0"); @@ -1065,7 +1066,7 @@ public async Task GetHostEntryAsync_ByIp_NoHost() [Fact] public async Task GetHostEntryAsync_ByManyIps() { - var client = new LookupClient(NameServer.GooglePublicDns); + using var client = new LookupClient(NameServer.GooglePublicDns); var nsServers = client.Query("google.com", QueryType.NS).Answers.NsRecords().ToArray(); Assert.True(nsServers.Length > 0, "Should have more than 0 NS servers"); @@ -1088,7 +1089,7 @@ public async Task GetHostEntryAsync_ByManyIps() [Fact] public void Lookup_SettingsFallback_UseClients() { - var client = new LookupClient(NameServer.CloudflareIPv6); + using var client = new LookupClient(NameServer.CloudflareIPv6); var settings = client.GetSettings(queryOptions: null); @@ -1099,7 +1100,7 @@ public void Lookup_SettingsFallback_UseClients() public void Lookup_Options_UseClientsAndResolvedServers() { // Specify one and auto resolve - var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare) { AutoResolveNameServers = true }); + using var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare) { AutoResolveNameServers = true }); Assert.True(client.NameServers.Count > 1); Assert.Contains(NameServer.Cloudflare, client.NameServers); @@ -1109,7 +1110,7 @@ public void Lookup_Options_UseClientsAndResolvedServers() public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified1() { // Specify one and auto resolve - var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare)); + using var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare)); Assert.Single(client.NameServers); Assert.Contains(NameServer.Cloudflare, client.NameServers); @@ -1119,7 +1120,7 @@ public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified1() public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified2() { // Specify one and auto resolve - var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare.Address)); + using var client = new LookupClient(new LookupClientOptions(NameServer.Cloudflare.Address)); Assert.Single(client.NameServers); Assert.Contains(NameServer.Cloudflare, client.NameServers); @@ -1129,7 +1130,7 @@ public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified2() public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified3() { // Specify one and auto resolve - var client = new LookupClient(new LookupClientOptions(new IPEndPoint(NameServer.Cloudflare.Address, 33))); + using var client = new LookupClient(new LookupClientOptions(new IPEndPoint(NameServer.Cloudflare.Address, 33))); Assert.Single(client.NameServers); Assert.Contains(new IPEndPoint(NameServer.Cloudflare.Address, 33), client.NameServers); @@ -1138,7 +1139,7 @@ public void Lookup_Options_AutoResolveDisabled_WhenServerIsSpecified3() [Fact] public void Lookup_SettingsFallback_UseClientsServers() { - var client = new LookupClient(NameServer.CloudflareIPv6); + using var client = new LookupClient(NameServer.CloudflareIPv6); // Test that the settings in the end has the name servers configured on the client above and // still the settings provided apart from the servers (everything else will not fallback to the client's settings...) @@ -1160,7 +1161,7 @@ public void Lookup_SettingsFallback_UseClientsServers() [Fact] public void Lookup_SettingsFallback_KeepProvidedServers1() { - var client = new LookupClient(NameServer.CloudflareIPv6); + using var client = new LookupClient(NameServer.CloudflareIPv6); var settings = client.GetSettings(queryOptions: new DnsQueryAndServerOptions(NameServer.GooglePublicDns)); @@ -1171,7 +1172,7 @@ public void Lookup_SettingsFallback_KeepProvidedServers1() [Fact] public void Lookup_SettingsFallback_KeepProvidedServers2() { - var client = new LookupClient(NameServer.CloudflareIPv6); + using var client = new LookupClient(NameServer.CloudflareIPv6); var settings = client.GetSettings(queryOptions: new DnsQueryAndServerOptions(IPAddress.Loopback)); @@ -1182,7 +1183,7 @@ public void Lookup_SettingsFallback_KeepProvidedServers2() [Fact] public void Lookup_SettingsFallback_KeepProvidedServers3() { - var client = new LookupClient(NameServer.CloudflareIPv6); + using var client = new LookupClient(NameServer.CloudflareIPv6); var settings = client.GetSettings(queryOptions: new DnsQueryAndServerOptions(new IPEndPoint(IPAddress.Loopback, 33))); @@ -1207,7 +1208,7 @@ public async Task Lookup_XidMismatch(int mismatchResponses, bool sync) }; using var server = new UdpServerMistmatchXid(serverEndpoint, mismatchResponses); - var client = new LookupClient(options); + using var client = new LookupClient(options); var dnsQuestion = new DnsQuestion("someservice", QueryType.TXT, QueryClass.IN); var response = sync ? client.Query(dnsQuestion) : await client.QueryAsync(dnsQuestion); @@ -1238,7 +1239,7 @@ public async Task Lookup_DuplicateUDPResponses(int duplicatesCount, bool sync) }; using var server = new UdpServerDuplicateResponses(serverEndpoint, duplicatesCount); - var client = new LookupClient(options); + using var client = new LookupClient(options); var dnsQuestion = new DnsQuestion("someservice", QueryType.TXT, QueryClass.IN); var response1 = sync ? client.Query(dnsQuestion) : await client.QueryAsync(dnsQuestion); diff --git a/test/DnsClient.Tests/NameServerTest.cs b/test/DnsClient.Tests/NameServerTest.cs index 709175cf..a1ad0737 100644 --- a/test/DnsClient.Tests/NameServerTest.cs +++ b/test/DnsClient.Tests/NameServerTest.cs @@ -66,5 +66,102 @@ public void ValidateNameResolutionPolicyDoesntThrowNormally() Assert.Null(ex); } + + [Fact] + public void EqualityA() + { + var a = new NameServer(NameServer.GooglePublicDns); + var b = new NameServer(NameServer.GooglePublicDns); + + Assert.Equal(a, b); + Assert.Equal(a, a); + } + + [Fact] + public void EqualityB() + { + var a = new NameServer(IPAddress.Loopback); + var b = new NameServer(IPAddress.Loopback); + + Assert.Equal(a, b); + } + + [Fact] + public void EqualityF() + { + var a = new NameServer(IPAddress.Loopback); + var b = new NameServer(IPAddress.IPv6Any); + + Assert.NotEqual(a, b); + } + + [Fact] + public void EqualityC() + { + var a = new NameServer(IPAddress.Loopback); + var b = new NameServer(IPAddress.Loopback, 111); + + Assert.NotEqual(a, b); + Assert.NotEqual(b, a); + } + + [Fact] + public void EqualityD() + { + var a = new NameServer(IPAddress.Loopback, "domain"); + var b = new NameServer(IPAddress.Loopback, "domain"); + + Assert.Equal(a, b); + } + + [Fact] + public void EqualityE() + { + var a = new NameServer(IPAddress.Loopback); + var b = new NameServer(IPAddress.Loopback, "domain"); + + Assert.Equal(a, b); + Assert.Equal(b, a); + } + + [Fact] + public void EqualityG() + { + var a = new NameServer(IPAddress.IPv6Any); + var b = new NameServer(IPAddress.Loopback, "domain"); + + Assert.NotEqual(a, b); + Assert.NotEqual(b, a); + } + + [Fact] + public void EqualityH() + { + var a = new NameServer(IPAddress.IPv6Any, "domain"); + var b = new NameServer(IPAddress.Loopback, "domain"); + + Assert.NotEqual(a, b); + Assert.NotEqual(b, a); + } + + [Fact] + public void EqualityI() + { + var a = new NameServer(IPAddress.IPv6Any, "domain"); + var b = new NameServer(IPAddress.Loopback, "domain2"); + + Assert.NotEqual(a, b); + Assert.NotEqual(b, a); + } + + [Fact] + public void EqualityJ() + { + var a = new NameServer(IPAddress.Loopback, "domain"); + var b = new NameServer(IPAddress.Loopback, "domain2"); + + Assert.Equal(a, b); + Assert.Equal(b, a); + } } }