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://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);
///