From b01a740cd8f30f9d11410d109dc45eab709ba2e4 Mon Sep 17 00:00:00 2001 From: Alan Edwardes Date: Sun, 26 Mar 2023 14:06:16 +0100 Subject: [PATCH] Deprecates DnsRoundRobinClient. --- Ae.Dns.sln | 14 +++---- README.md | 16 ++++---- samples/AdvancedUdpServer/Program.cs | 4 +- samples/BasicHttpClientMiddleware/Program.cs | 2 +- samples/BasicHttpServer/Program.cs | 2 +- samples/BasicUdpServer/Program.cs | 2 +- .../Program.cs | 2 +- .../RandomClient.csproj} | 0 src/Ae.Dns.Client/DnsRandomClient.cs | 39 +++++++++++++++++++ src/Ae.Dns.Client/DnsRoundRobinClient.cs | 4 ++ 10 files changed, 64 insertions(+), 21 deletions(-) rename samples/{RoundRobinClient => RandomClient}/Program.cs (83%) rename samples/{RoundRobinClient/RoundRobinClient.csproj => RandomClient/RandomClient.csproj} (100%) create mode 100644 src/Ae.Dns.Client/DnsRandomClient.cs diff --git a/Ae.Dns.sln b/Ae.Dns.sln index 7146670..635ac6b 100644 --- a/Ae.Dns.sln +++ b/Ae.Dns.sln @@ -40,8 +40,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdvancedHttpClient", "sampl EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicUdpClient", "samples\BasicUdpClient\BasicUdpClient.csproj", "{3644AE12-0D00-4A22-97AB-1D316507562C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RoundRobinClient", "samples\RoundRobinClient\RoundRobinClient.csproj", "{EC10205A-44D0-4344-8A36-FBE89EC9AAA6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CachingClient", "samples\CachingClient\CachingClient.csproj", "{BD7AAA9D-221A-4492-91C5-91E066A5BA14}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BasicUdpServer", "samples\BasicUdpServer\BasicUdpServer.csproj", "{C4DC5DEF-66C0-47A8-9127-A8BEE7334809}" @@ -56,6 +54,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AdvancedHttpClientMiddlewar EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RacerClient", "samples\RacerClient\RacerClient.csproj", "{5E04E0A5-8BFC-423F-88D4-CAF0368CCC40}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RandomClient", "samples\RandomClient\RandomClient.csproj", "{1864C2EF-CA84-4A56-BB0A-AA29CDB21A04}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -110,10 +110,6 @@ Global {3644AE12-0D00-4A22-97AB-1D316507562C}.Debug|Any CPU.Build.0 = Debug|Any CPU {3644AE12-0D00-4A22-97AB-1D316507562C}.Release|Any CPU.ActiveCfg = Release|Any CPU {3644AE12-0D00-4A22-97AB-1D316507562C}.Release|Any CPU.Build.0 = Release|Any CPU - {EC10205A-44D0-4344-8A36-FBE89EC9AAA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EC10205A-44D0-4344-8A36-FBE89EC9AAA6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EC10205A-44D0-4344-8A36-FBE89EC9AAA6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EC10205A-44D0-4344-8A36-FBE89EC9AAA6}.Release|Any CPU.Build.0 = Release|Any CPU {BD7AAA9D-221A-4492-91C5-91E066A5BA14}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BD7AAA9D-221A-4492-91C5-91E066A5BA14}.Debug|Any CPU.Build.0 = Debug|Any CPU {BD7AAA9D-221A-4492-91C5-91E066A5BA14}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -142,6 +138,10 @@ Global {5E04E0A5-8BFC-423F-88D4-CAF0368CCC40}.Debug|Any CPU.Build.0 = Debug|Any CPU {5E04E0A5-8BFC-423F-88D4-CAF0368CCC40}.Release|Any CPU.ActiveCfg = Release|Any CPU {5E04E0A5-8BFC-423F-88D4-CAF0368CCC40}.Release|Any CPU.Build.0 = Release|Any CPU + {1864C2EF-CA84-4A56-BB0A-AA29CDB21A04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1864C2EF-CA84-4A56-BB0A-AA29CDB21A04}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1864C2EF-CA84-4A56-BB0A-AA29CDB21A04}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1864C2EF-CA84-4A56-BB0A-AA29CDB21A04}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -159,7 +159,6 @@ Global {77A7BCB5-5724-489D-ACA4-CDFD1966D6D7} = {7C20B305-A37E-479F-83B2-79606FBF6033} {7E8565CB-026A-4E3C-BE37-F78EFF846865} = {7C20B305-A37E-479F-83B2-79606FBF6033} {3644AE12-0D00-4A22-97AB-1D316507562C} = {7C20B305-A37E-479F-83B2-79606FBF6033} - {EC10205A-44D0-4344-8A36-FBE89EC9AAA6} = {7C20B305-A37E-479F-83B2-79606FBF6033} {BD7AAA9D-221A-4492-91C5-91E066A5BA14} = {7C20B305-A37E-479F-83B2-79606FBF6033} {C4DC5DEF-66C0-47A8-9127-A8BEE7334809} = {7C20B305-A37E-479F-83B2-79606FBF6033} {7E50BBCD-12E0-41C8-A81B-E9D14064BE40} = {7C20B305-A37E-479F-83B2-79606FBF6033} @@ -167,6 +166,7 @@ Global {92037BF8-D2C4-499E-9802-C839C8B24A1B} = {7C20B305-A37E-479F-83B2-79606FBF6033} {9BE0395F-3549-45C5-9E22-0E6735FB78F2} = {7C20B305-A37E-479F-83B2-79606FBF6033} {5E04E0A5-8BFC-423F-88D4-CAF0368CCC40} = {7C20B305-A37E-479F-83B2-79606FBF6033} + {1864C2EF-CA84-4A56-BB0A-AA29CDB21A04} = {7C20B305-A37E-479F-83B2-79606FBF6033} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2ABE6B23-17A6-4850-8DE8-02A4BF5684DC} diff --git a/README.md b/README.md index 5a8c38f..c79ee8d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **API Documentation: https://alanedwardes.github.io/docs/Ae.Dns/** A pure C# implementation of a DNS client, server and configurable caching/filtering layer. This project offers the following packages: -* [Ae.Dns.Client](#aednsclient) - HTTP and UDP DNS clients with caching and round-robin capabilities +* [Ae.Dns.Client](#aednsclient) - HTTP and UDP DNS clients with caching capabilities * [Ae.Dns.Server](#aednsserver) - Standard UDP DNS server * [Ae.Dns.Server.Http](#aednsserverhttp) - HTTP DNS server (if coupled with SSL, a DoH server) * [Ae.Dns.Protocol](#aednsprotocol) - Low level DNS wire protocol round-trip handling used on the client and server @@ -10,7 +10,7 @@ A pure C# implementation of a DNS client, server and configurable caching/filter ## Ae.Dns.Client [![](https://img.shields.io/nuget/v/Ae.Dns.Client) ![](https://img.shields.io/badge/framework-netstandard2.0-blue)](https://www.nuget.org/packages/Ae.Dns.Client/) -Offers both HTTP(S) and UDP DNS clients, with a simple round robin client implementation. +Offers both HTTP(S) and UDP DNS clients, with a simple random client implementation. ### Basic HTTPS Client Usage This example is a very simple setup of the `DnsHttpClient` using the CloudFlare DNS over HTTPS resolver. @@ -26,18 +26,18 @@ This example is a basic setup of the `DnsUdpClient` using the primary CloudFlare See [samples/BasicUdpClient/Program.cs](samples/BasicUdpClient/Program.cs) -### Round Robin Client Usage -This example uses multiple upstream `IDnsClient` implementations in a round-robin fashion using `DnsRoundRobinClient`. Note that multiple protocols can be mixed, both the `DnsUdpClient` and `DnsHttpClient` can be used here since they implement `IDnsClient`. +### Random Client Usage +This example uses multiple upstream `IDnsClient` implementations in a random fashion using `DnsRandomClient`. Note that multiple protocols can be mixed, both the `DnsUdpClient` and `DnsHttpClient` can be used here since they implement `IDnsClient`. -See [samples/RoundRobinClient/Program.cs](samples/RoundRobinClient/Program.cs) +See [samples/RandomClient/Program.cs](samples/RandomClient/Program.cs) ### Racer Client Usage -This example uses multiple (two or more) upstream `IDnsClient` implementations and races them using `DnsRacerClient`. Two queries are sent in parallel, and the fastest result "wins" (is returned). If a query faults, the other query result is used. As with the round robin-client, multiple protocols can be mixed, both the `DnsUdpClient` and `DnsHttpClient` can be used here since they implement `IDnsClient`. +This example uses multiple (two or more) upstream `IDnsClient` implementations and races them using `DnsRacerClient`. Two queries are sent in parallel, and the fastest result "wins" (is returned). If a query faults, the other query result is used. As with the random client, multiple protocols can be mixed, both the `DnsUdpClient` and `DnsHttpClient` can be used here since they implement `IDnsClient`. See [samples/RacerClient/Program.cs](samples/RacerClient/Program.cs) ### Caching Client Usage -This example uses the `DnsCachingClient` to cache queries into a `MemoryCache`, so that the answer is not retrieved from the upstream if the answer is within its TTL. Note that this can be combined with the `DnsRoundRobinClient`, so the cache can be backed by multiple upstream clients (it just accepts `IDnsClient`). +This example uses the `DnsCachingClient` to cache queries into a `MemoryCache`, so that the answer is not retrieved from the upstream if the answer is within its TTL. Note that this can be combined with the `DnsRandomClient`, so the cache can be backed by multiple upstream clients (it just accepts `IDnsClient`). See [samples/CachingClient/Program.cs](samples/CachingClient/Program.cs) @@ -52,7 +52,7 @@ A example UDP server which forwards all queries via UDP to the CloudFlare DNS re See [samples/BasicUdpServer/Program.cs](samples/BasicUdpServer/Program.cs) ### Advanced UDP Server -A more advanced UDP server which uses the `DnsCachingClient` and `DnsRoundRobinClient` to cache DNS answers from multiple upstream clients, and the `RemoteSetFilter` to block domains from a remote hosts file. +A more advanced UDP server which uses the `DnsCachingClient` and `DnsRandomClient` to cache DNS answers from multiple upstream clients, and the `RemoteSetFilter` to block domains from a remote hosts file. See [samples/AdvancedUdpServer/Program.cs](samples/AdvancedUdpServer/Program.cs) diff --git a/samples/AdvancedUdpServer/Program.cs b/samples/AdvancedUdpServer/Program.cs index aed0fea..daa1ba6 100644 --- a/samples/AdvancedUdpServer/Program.cs +++ b/samples/AdvancedUdpServer/Program.cs @@ -11,10 +11,10 @@ using IDnsClient google2 = new DnsUdpClient(IPAddress.Parse("8.8.4.4")); // Aggregate all clients into one -using IDnsClient roundRobinClient = new DnsRoundRobinClient(cloudFlare1, cloudFlare2, google1, google2); +using IDnsClient randomClient = new DnsRandomClient(cloudFlare1, cloudFlare2, google1, google2); // Add the caching layer -using IDnsClient cacheClient = new DnsCachingClient(roundRobinClient, new MemoryCache("dns")); +using IDnsClient cacheClient = new DnsCachingClient(randomClient, new MemoryCache("dns")); using var httpClient = new HttpClient(); diff --git a/samples/BasicHttpClientMiddleware/Program.cs b/samples/BasicHttpClientMiddleware/Program.cs index f240fb6..7b47c11 100644 --- a/samples/BasicHttpClientMiddleware/Program.cs +++ b/samples/BasicHttpClientMiddleware/Program.cs @@ -2,7 +2,7 @@ using Ae.Dns.Protocol; using Ae.Dns.Client; -// Can use the HTTPS, UDP, round robin or caching clients - any IDnsClient +// Can use the HTTPS, UDP, random or caching clients - any IDnsClient using IDnsClient dnsClient = new DnsUdpClient(IPAddress.Parse("1.1.1.1")); // Create an HttpClient with the DnsDelegatingHandler diff --git a/samples/BasicHttpServer/Program.cs b/samples/BasicHttpServer/Program.cs index 57dd710..fc86559 100644 --- a/samples/BasicHttpServer/Program.cs +++ b/samples/BasicHttpServer/Program.cs @@ -3,7 +3,7 @@ using Ae.Dns.Server.Http; using System.Net; -// Can use the HTTPS, UDP, round robin or caching clients - any IDnsClient +// Can use the HTTPS, UDP, random or caching clients - any IDnsClient using IDnsClient dnsClient = new DnsUdpClient(IPAddress.Parse("1.1.1.1")); // Create the HTTP server - see overloads for configuration options diff --git a/samples/BasicUdpServer/Program.cs b/samples/BasicUdpServer/Program.cs index e921c24..3203750 100644 --- a/samples/BasicUdpServer/Program.cs +++ b/samples/BasicUdpServer/Program.cs @@ -4,7 +4,7 @@ using Ae.Dns.Server; using System.Net; -// Can use the HTTPS, UDP, round robin or caching clients - any IDnsClient +// Can use the HTTPS, UDP, random or caching clients - any IDnsClient using IDnsClient dnsClient = new DnsUdpClient(IPAddress.Parse("1.1.1.1")); // Allow anything that isn't www.google.com diff --git a/samples/RoundRobinClient/Program.cs b/samples/RandomClient/Program.cs similarity index 83% rename from samples/RoundRobinClient/Program.cs rename to samples/RandomClient/Program.cs index 97b1340..d1531b8 100644 --- a/samples/RoundRobinClient/Program.cs +++ b/samples/RandomClient/Program.cs @@ -7,7 +7,7 @@ using IDnsClient google1 = new DnsUdpClient(IPAddress.Parse("8.8.8.8")); using IDnsClient google2 = new DnsUdpClient(IPAddress.Parse("8.8.4.4")); -using IDnsClient dnsClient = new DnsRoundRobinClient(cloudFlare1, cloudFlare2, google1, google2); +using IDnsClient dnsClient = new DnsRandomClient(cloudFlare1, cloudFlare2, google1, google2); // Run an A query for google.com DnsMessage answer = await dnsClient.Query(DnsQueryFactory.CreateQuery("google.com")); diff --git a/samples/RoundRobinClient/RoundRobinClient.csproj b/samples/RandomClient/RandomClient.csproj similarity index 100% rename from samples/RoundRobinClient/RoundRobinClient.csproj rename to samples/RandomClient/RandomClient.csproj diff --git a/src/Ae.Dns.Client/DnsRandomClient.cs b/src/Ae.Dns.Client/DnsRandomClient.cs new file mode 100644 index 0000000..04c847b --- /dev/null +++ b/src/Ae.Dns.Client/DnsRandomClient.cs @@ -0,0 +1,39 @@ +using Ae.Dns.Protocol; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Ae.Dns.Client +{ + /// + /// A client consisting of multiple instances which are picked at random. + /// + public sealed class DnsRandomClient : IDnsClient + { + private readonly IReadOnlyCollection _dnsClients; + + /// + /// Create a new random DNS client selector using the specified instances to delegate to. + /// + /// The enumerable of DNS clients to use. + public DnsRandomClient(IEnumerable dnsClients) => _dnsClients = dnsClients.ToList(); + + /// + /// Create a new random DNS client selector using the specified instances to delegate to. + /// + /// The array of DNS clients to use. + public DnsRandomClient(params IDnsClient[] dnsClients) => _dnsClients = dnsClients; + + private IDnsClient GetRandomClient() => _dnsClients.OrderBy(x => Guid.NewGuid()).First(); + + /// + public Task Query(DnsMessage query, CancellationToken token) => GetRandomClient().Query(query, token); + + /// + public void Dispose() + { + } + } +} diff --git a/src/Ae.Dns.Client/DnsRoundRobinClient.cs b/src/Ae.Dns.Client/DnsRoundRobinClient.cs index 234a9b6..dd6d4e9 100644 --- a/src/Ae.Dns.Client/DnsRoundRobinClient.cs +++ b/src/Ae.Dns.Client/DnsRoundRobinClient.cs @@ -10,6 +10,7 @@ namespace Ae.Dns.Client /// /// A client consisting of multiple instances which are picked at random. /// + [Obsolete("This client does not do round robin. Please use DnsRandomClient")] public sealed class DnsRoundRobinClient : IDnsClient { private readonly IReadOnlyCollection _dnsClients; @@ -18,17 +19,20 @@ public sealed class DnsRoundRobinClient : IDnsClient /// Create a new round-robin DNS client using the specified instances to delegate to. /// /// The enumerable of DNS clients to use. + [Obsolete("This client does not do round robin. Please use DnsRandomClient")] public DnsRoundRobinClient(IEnumerable dnsClients) => _dnsClients = dnsClients.ToList(); /// /// Create a new round-robin DNS client using the specified instances to delegate to. /// /// The array of DNS clients to use. + [Obsolete("This client does not do round robin. Please use DnsRandomClient")] public DnsRoundRobinClient(params IDnsClient[] dnsClients) => _dnsClients = dnsClients; private IDnsClient GetRandomClient() => _dnsClients.OrderBy(x => Guid.NewGuid()).First(); /// + [Obsolete("This client does not do round robin. Please use DnsRandomClient")] public Task Query(DnsMessage query, CancellationToken token) => GetRandomClient().Query(query, token); ///