Skip to content

Commit 828c463

Browse files
authored
Removing UDP client pooling (#146)
Removing UDP client pooling + some bug fixes: #132, #145, #136, #133
1 parent d56cb12 commit 828c463

26 files changed

+181
-245
lines changed

.editorconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ dotnet_diagnostic.CA1835.severity = silent
181181

182182
# All the style rules we want to enforce during build...
183183
dotnet_diagnostic.CA2211.severity = warning
184+
dotnet_diagnostic.CA2007.severity = warning
185+
dotnet_diagnostic.CA1031.severity = suggestion
184186

185187
dotnet_diagnostic.IDE0001.severity = warning
186188
dotnet_diagnostic.IDE0003.severity = warning

samples/MiniDig/MiniDig.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net50</TargetFramework>
4+
<TargetFramework>net5.0</TargetFramework>
55
<AssemblyName>MiniDig</AssemblyName>
66
<OutputType>Exe</OutputType>
77
<PackageId>MiniDig</PackageId>

samples/MiniDig/PerfCommand.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ protected override async Task<int> Execute()
9494

9595
tasks.Add(CollectPrint());
9696

97-
await Task.WhenAny(tasks.ToArray());
97+
await Task.WhenAny(tasks.ToArray()).ConfigureAwait(false);
9898

9999
double elapsedSeconds = sw.ElapsedMilliseconds / 1000d;
100100

@@ -120,7 +120,7 @@ private async Task CollectPrint()
120120
while (waitCount < _runtime)
121121
{
122122
waitCount++;
123-
await Task.Delay(1000);
123+
await Task.Delay(1000).ConfigureAwait(false);
124124

125125
_spinner.Message = $"Requests per sec: {_reportExcecutions:N2}.";
126126
Interlocked.Exchange(ref _reportExcecutions, 0);
@@ -143,7 +143,7 @@ private async Task ExcecuteRun(int numTasks = 8)
143143
tasks.Add(Job());
144144
}
145145

146-
await Task.WhenAll(tasks);
146+
await Task.WhenAll(tasks).ConfigureAwait(false);
147147
}
148148

149149
async Task Job()
@@ -153,12 +153,12 @@ async Task Job()
153153
IDnsQueryResponse response;
154154
if (!_runSync)
155155
{
156-
response = await lookup.QueryAsync(_query, QueryType.A);
156+
response = await lookup.QueryAsync(_query, QueryType.A).ConfigureAwait(false);
157157
}
158158
else
159159
{
160-
response = await Task.Run(() => lookup.Query(_query, QueryType.A));
161-
await Task.Delay(0);
160+
response = await Task.Run(() => lookup.Query(_query, QueryType.A)).ConfigureAwait(false);
161+
await Task.Delay(0).ConfigureAwait(false);
162162
}
163163

164164
Interlocked.Increment(ref _allExcecutions);

samples/MiniDig/RandomCommand.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ protected override async Task<int> Execute()
104104
tasks.Add(CollectPrint());
105105
try
106106
{
107-
await Task.WhenAny(tasks.ToArray());
107+
await Task.WhenAny(tasks.ToArray()).ConfigureAwait(false);
108108
}
109109
catch (Exception ex)
110110
{
@@ -141,7 +141,7 @@ private async Task CollectPrint()
141141
while (_running && waitCount < _runtime)
142142
{
143143
waitCount++;
144-
await Task.Delay(1000);
144+
await Task.Delay(1000).ConfigureAwait(false);
145145

146146
var serverUpdate = from good in _successByServer
147147
join fail in _failByServer on good.Key equals fail.Key into all
@@ -175,11 +175,11 @@ private async Task ExcecuteRun()
175175

176176
if (!_runSync)
177177
{
178-
response = await _lookup.QueryAsync(query, QueryType.A);
178+
response = await _lookup.QueryAsync(query, QueryType.A).ConfigureAwait(false);
179179
}
180180
else
181181
{
182-
response = await Task.Run(() => _lookup.Query(query, QueryType.A));
182+
response = await Task.Run(() => _lookup.Query(query, QueryType.A)).ConfigureAwait(false);
183183
}
184184

185185
Interlocked.Increment(ref _allExcecutions);

samples/MiniDig/Spinner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ private async Task Spin()
8686
Console.SetCursorPosition(0, Console.CursorTop);
8787
Console.ForegroundColor = _oldColor;
8888
Console.CursorVisible = true;
89-
await Task.Delay(100, _token);
89+
await Task.Delay(100, _token).ConfigureAwait(false);
9090
}
9191
}
9292
}

src/DnsClient/DnsClient.csproj

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<VersionPrefix>1.6.0</VersionPrefix>
44
<VersionSuffix Condition="'$(VersionSuffix)'!='' AND '$(BuildNumber)' != ''">$(VersionSuffix)-$(BuildNumber)</VersionSuffix>
55

6-
<TargetFrameworks>netstandard1.3;netstandard2.0;netstandard2.1;net50;net45;net471</TargetFrameworks>
6+
<TargetFrameworks>net5.0;netstandard1.3;netstandard2.0;netstandard2.1;net45;net471</TargetFrameworks>
77
<DebugType>full</DebugType>
88

99
<Product>DnsClient.NET</Product>
@@ -35,6 +35,7 @@
3535
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
3636
<EnableNETAnalyzers>true</EnableNETAnalyzers>
3737
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
38+
<AnalysisMode>Default</AnalysisMode>
3839
</PropertyGroup>
3940

4041
<ItemGroup>
@@ -64,10 +65,4 @@
6465
<PackageReference Include="System.Diagnostics.TraceSource" Version="4.3.0" />
6566
</ItemGroup>
6667

67-
<!--<ItemGroup>
68-
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="5.0.3">
69-
<PrivateAssets>all</PrivateAssets>
70-
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
71-
</PackageReference>
72-
</ItemGroup>-->
7368
</Project>

src/DnsClient/DnsDatagramReader.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Linq;
45
using System.Net;
56
using System.Text;
@@ -78,7 +79,7 @@ public static string ParseString(DnsDatagramReader reader, int length)
7879

7980
if (b < 32 || b > 126)
8081
{
81-
builder.Append("\\" + b.ToString("000"));
82+
builder.Append("\\" + b.ToString("000", CultureInfo.InvariantCulture));
8283
}
8384
else if (c == ';')
8485
{

src/DnsClient/DnsMessageHandler.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.IO;
23
using System.Net;
34
using System.Net.Sockets;
45
using System.Threading;
@@ -27,8 +28,13 @@ public abstract Task<DnsResponseMessage> QueryAsync(
2728

2829
// Transient errors will be retried on the same NameServer before the resolver moves on
2930
// to the next configured NameServer (if any).
30-
public static bool IsTransientException<T>(T exception) where T : Exception
31+
public static bool IsTransientException(Exception exception)
3132
{
33+
if (exception is IOException)
34+
{
35+
exception = exception?.InnerException ?? exception;
36+
}
37+
3238
if (exception is SocketException socketException)
3339
{
3440
// I think those are reasonable socket errors which can be retried
@@ -50,7 +56,17 @@ public static bool IsTransientException<T>(T exception) where T : Exception
5056

5157
protected static void ValidateResponse(DnsRequestMessage request, DnsResponseMessage response)
5258
{
53-
if (request != null && response != null && request.Header.Id != response.Header.Id)
59+
if (request is null)
60+
{
61+
throw new ArgumentNullException(nameof(request));
62+
}
63+
64+
if (response is null)
65+
{
66+
throw new ArgumentNullException(nameof(response));
67+
}
68+
69+
if (request.Header.Id != response.Header.Id)
5470
{
5571
throw new DnsXidMismatchException(request.Header.Id, response.Header.Id);
5672
}

src/DnsClient/DnsTcpMessageHandler.cs

Lines changed: 25 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4-
using System.IO;
54
using System.Linq;
65
using System.Net;
76
using System.Net.Sockets;
@@ -40,12 +39,13 @@ public override async Task<DnsResponseMessage> QueryAsync(
4039
cancellationToken.ThrowIfCancellationRequested();
4140

4241
ClientPool pool;
43-
ClientPool.ClientEntry entry = null;
4442
while (!_pools.TryGetValue(server, out pool))
4543
{
4644
_pools.TryAdd(server, new ClientPool(true, server));
4745
}
4846

47+
var entry = await pool.GetNextClient().ConfigureAwait(false);
48+
4949
using var cancelCallback = cancellationToken.Register(() =>
5050
{
5151
if (entry == null)
@@ -56,33 +56,21 @@ public override async Task<DnsResponseMessage> QueryAsync(
5656
entry.DisposeClient();
5757
});
5858

59-
DnsResponseMessage response = null;
60-
61-
// Simple retry in case the pooled clients are
62-
var tries = 0;
63-
while (response == null && tries < 3)
59+
try
6460
{
65-
tries++;
66-
entry = await pool.GetNextClient().ConfigureAwait(false);
61+
var response = await QueryAsyncInternal(entry.Client, request, cancellationToken).ConfigureAwait(false);
6762

68-
cancellationToken.ThrowIfCancellationRequested();
63+
ValidateResponse(request, response);
6964

70-
response = await QueryAsyncInternal(entry.Client, request, cancellationToken)
71-
.ConfigureAwait(false);
65+
pool.Enqueue(entry);
7266

73-
if (response != null)
74-
{
75-
pool.Enqueue(entry);
76-
}
77-
else
78-
{
79-
entry.DisposeClient();
80-
}
67+
return response;
68+
}
69+
catch
70+
{
71+
entry.DisposeClient();
72+
throw;
8173
}
82-
83-
ValidateResponse(request, response);
84-
85-
return response;
8674
}
8775

8876
private async Task<DnsResponseMessage> QueryAsyncInternal(TcpClient client, DnsRequestMessage request, CancellationToken cancellationToken)
@@ -107,7 +95,8 @@ private async Task<DnsResponseMessage> QueryAsyncInternal(TcpClient client, DnsR
10795

10896
if (!stream.CanRead)
10997
{
110-
return null;
98+
// might retry
99+
throw new TimeoutException();
111100
}
112101

113102
cancellationToken.ThrowIfCancellationRequested();
@@ -117,33 +106,25 @@ private async Task<DnsResponseMessage> QueryAsyncInternal(TcpClient client, DnsR
117106
do
118107
{
119108
int length;
120-
try
109+
using (var lengthBuffer = new PooledBytes(2))
121110
{
122-
//length = stream.ReadByte() << 8 | stream.ReadByte();
123-
using (var lengthBuffer = new PooledBytes(2))
111+
int bytesReceived = 0, read;
112+
while ((bytesReceived += (read = await stream.ReadAsync(lengthBuffer.Buffer, bytesReceived, 2, cancellationToken).ConfigureAwait(false))) < 2)
124113
{
125-
int bytesReceived = 0, read;
126-
while ((bytesReceived += (read = await stream.ReadAsync(lengthBuffer.Buffer, bytesReceived, 2, cancellationToken).ConfigureAwait(false))) < 2)
114+
if (read <= 0)
127115
{
128-
if (read <= 0)
129-
{
130-
// disconnected, might retry
131-
return null;
132-
}
116+
// disconnected, might retry
117+
throw new TimeoutException();
133118
}
134-
135-
length = lengthBuffer.Buffer[0] << 8 | lengthBuffer.Buffer[1];
136119
}
137-
}
138-
catch (Exception ex) when (ex is IOException || ex is SocketException)
139-
{
140-
return null;
120+
121+
length = lengthBuffer.Buffer[0] << 8 | lengthBuffer.Buffer[1];
141122
}
142123

143124
if (length <= 0)
144125
{
145-
// server signals close/disconnecting
146-
return null;
126+
// server signals close/disconnecting, might retry
127+
throw new TimeoutException();
147128
}
148129

149130
using (var memory = new PooledBytes(length))
@@ -157,7 +138,7 @@ private async Task<DnsResponseMessage> QueryAsyncInternal(TcpClient client, DnsR
157138
if (read <= 0)
158139
{
159140
// disconnected
160-
return null;
141+
throw new TimeoutException();
161142
}
162143
if (bytesReceived + readSize > length)
163144
{

0 commit comments

Comments
 (0)