diff --git a/src/DnsClient/DnsMessageHandler.cs b/src/DnsClient/DnsMessageHandler.cs index 8f33c1e7..7d089c9b 100644 --- a/src/DnsClient/DnsMessageHandler.cs +++ b/src/DnsClient/DnsMessageHandler.cs @@ -15,7 +15,7 @@ internal enum DnsMessageHandleType TCP } - internal abstract class DnsMessageHandler + internal abstract class DnsMessageHandler : IDisposable { public abstract DnsMessageHandleType Type { get; } @@ -170,5 +170,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 a7e01c95..b57c846a 100644 --- a/src/DnsClient/DnsTcpMessageHandler.cs +++ b/src/DnsClient/DnsTcpMessageHandler.cs @@ -11,18 +11,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)) @@ -32,7 +36,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(() => { @@ -69,6 +73,11 @@ public override async Task QueryAsync( DnsRequestMessage request, CancellationToken cancellationToken) { + if (_disposedValue) + { + throw new ObjectDisposedException(nameof(DnsTcpMessageHandler)); + } + cancellationToken.ThrowIfCancellationRequested(); ClientPool pool; @@ -77,7 +86,7 @@ public override async Task QueryAsync( _pools.TryAdd(server, new ClientPool(true, server)); } - var entry = await pool.GetNextClientAsync().ConfigureAwait(false); + var entry = await pool.GetNextClientAsync(cancellationToken).ConfigureAwait(false); using var cancelCallback = cancellationToken.Register(() => { @@ -281,7 +290,22 @@ 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 = false; private readonly bool _enablePool; @@ -294,7 +318,7 @@ public ClientPool(bool enablePool, IPEndPoint endpoint) _endpoint = endpoint; } - public ClientEntry GetNextClient() + public ClientEntry GetNextClient(CancellationToken cancellationToken) { if (_disposedValue) { @@ -306,20 +330,54 @@ public ClientEntry GetNextClient() { while (entry == null && !TryDequeue(out entry)) { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily) { LingerState = new LingerOption(true, 0) }, _endpoint); - entry.Client.Connect(_endpoint.Address, _endpoint.Port); + entry = ConnectNew(cancellationToken); } } else { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily), _endpoint); - entry.Client.Connect(_endpoint.Address, _endpoint.Port); + entry = ConnectNew(cancellationToken); } return entry; } - public async Task GetNextClientAsync() + 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) { @@ -331,19 +389,57 @@ public async Task GetNextClientAsync() { while (entry == null && !TryDequeue(out entry)) { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily) { LingerState = new LingerOption(true, 0) }, _endpoint); - await entry.Client.ConnectAsync(_endpoint.Address, _endpoint.Port).ConfigureAwait(false); + entry = await ConnectNewAsync(cancellationToken).ConfigureAwait(false); } } else { - entry = new ClientEntry(new TcpClient(_endpoint.AddressFamily), _endpoint); - await entry.Client.ConnectAsync(_endpoint.Address, _endpoint.Port).ConfigureAwait(false); + 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) @@ -397,29 +493,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) @@ -432,11 +519,7 @@ public void DisposeClient() { try { -#if !NET45 Client.Dispose(); -#else - Client.Close(); -#endif } catch { } } diff --git a/src/DnsClient/DnsUdpMessageHandler.cs b/src/DnsClient/DnsUdpMessageHandler.cs index af61bd00..20be1de6 100644 --- a/src/DnsClient/DnsUdpMessageHandler.cs +++ b/src/DnsClient/DnsUdpMessageHandler.cs @@ -1,6 +1,5 @@ using System; using System.Buffers; -using System.Collections.Concurrent; using System.Net; using System.Net.Sockets; using System.Threading; diff --git a/src/DnsClient/ILookupClient.cs b/src/DnsClient/ILookupClient.cs index e1e62734..895313ba 100644 --- a/src/DnsClient/ILookupClient.cs +++ b/src/DnsClient/ILookupClient.cs @@ -60,4 +60,4 @@ public interface ILookupClient : IDnsQuery #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member } -} \ No newline at end of file +} diff --git a/src/DnsClient/LookupClient.cs b/src/DnsClient/LookupClient.cs index 33a7c676..65d0b7de 100644 --- a/src/DnsClient/LookupClient.cs +++ b/src/DnsClient/LookupClient.cs @@ -36,7 +36,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; @@ -62,6 +62,7 @@ public class LookupClient : ILookupClient, IDnsQuery private readonly SkipWorker _skipper = null; private IReadOnlyCollection _resolvedNameServers; + private bool _disposedValue; /// public IReadOnlyCollection NameServers => Settings.NameServers; @@ -370,7 +371,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) { @@ -427,7 +428,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) @@ -1787,6 +1790,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 ce57a58c..2417a5e1 100644 --- a/test-other/OldReference/TestLookupClient.cs +++ b/test-other/OldReference/TestLookupClient.cs @@ -51,7 +51,7 @@ public LookupClient SetNonDefaults() 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); @@ -71,7 +71,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 c6f1ecb4..195cd11f 100644 --- a/test/DnsClient.Tests/LookupTest.cs +++ b/test/DnsClient.Tests/LookupTest.cs @@ -30,7 +30,7 @@ static LookupTest() [Fact] public async Task TestingFor_LeakyMemory() { - var client = new LookupClient( + using var client = new LookupClient( new LookupClientOptions() { UseCache = false, @@ -57,7 +57,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, @@ -109,7 +109,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())) @@ -148,7 +148,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())) @@ -197,7 +197,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); @@ -211,7 +212,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); @@ -265,7 +266,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 @@ -285,7 +286,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 @@ -306,7 +307,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 @@ -326,7 +327,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 @@ -347,7 +348,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 @@ -367,7 +368,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 @@ -388,7 +389,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 @@ -402,7 +403,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 @@ -418,7 +419,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, @@ -435,7 +436,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, @@ -452,7 +453,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, @@ -469,7 +470,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, @@ -489,7 +490,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, @@ -510,7 +511,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, @@ -530,7 +531,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, @@ -550,7 +551,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, @@ -571,7 +572,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 @@ -590,7 +591,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 @@ -609,7 +610,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); @@ -618,7 +619,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); @@ -627,7 +628,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); @@ -636,7 +637,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()); @@ -646,7 +647,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()); @@ -656,7 +657,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); @@ -666,7 +667,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); @@ -676,7 +677,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()); @@ -687,7 +688,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()); @@ -698,7 +699,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()); @@ -708,7 +709,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()); @@ -718,7 +719,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()); @@ -729,7 +730,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()); @@ -740,7 +741,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()); @@ -751,7 +752,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()); @@ -762,7 +763,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); @@ -772,7 +773,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); @@ -782,7 +783,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); @@ -793,7 +794,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); @@ -806,7 +807,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); @@ -818,7 +819,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()); @@ -835,7 +836,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()); @@ -857,7 +858,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); @@ -867,7 +868,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"); @@ -879,7 +880,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 }); @@ -894,7 +895,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(""); @@ -904,7 +905,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"); @@ -916,7 +917,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 @@ -930,7 +931,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"); @@ -940,7 +941,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 @@ -954,7 +955,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 }); @@ -981,7 +982,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"); @@ -993,7 +994,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"); @@ -1005,7 +1006,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"); @@ -1017,7 +1018,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 @@ -1031,7 +1032,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("")); } @@ -1039,7 +1040,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"); @@ -1051,7 +1052,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"); @@ -1061,7 +1062,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"); @@ -1084,7 +1085,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); @@ -1095,7 +1096,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); @@ -1105,7 +1106,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); @@ -1115,7 +1116,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); @@ -1125,7 +1126,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); @@ -1134,7 +1135,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...) @@ -1156,7 +1157,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)); @@ -1167,7 +1168,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)); @@ -1178,7 +1179,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))); @@ -1203,7 +1204,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); @@ -1234,7 +1235,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 53fbe42a..67b4cdfa 100644 --- a/test/DnsClient.Tests/NameServerTest.cs +++ b/test/DnsClient.Tests/NameServerTest.cs @@ -62,5 +62,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); + } } }