Code
·
89 lines
·
2523 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89using System.Net;
using System.Net.Sockets;
namespace MailSharp.DNS;
public partial class Resolver
{
private async Task<Response> GetResponseAsync(IPEndPoint server, Request request)
{
request.Header.ID = (ushort)Interlocked.Increment(ref uniqueId);
request.Header.RD = recursion;
return transportType switch
{
TransportType.Udp => await UdpRequestAsync(server, request),
TransportType.Tcp => await TcpRequestAsync(server, request),
_ => new Response { ErrorMessage = "Unknown TransportType" }
};
}
private async Task<Response> UdpRequestAsync(IPEndPoint server, Request request)
{
var buffer = new byte[512];
for (int attempt = 0; attempt < retries; attempt++)
{
using var socket = new Socket(server.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
socket.ReceiveTimeout = timeoutSeconds * 1000;
try
{
await socket.SendToAsync(request.Data.ToArray(), SocketFlags.None, server);
var received = await socket.ReceiveAsync(buffer, SocketFlags.None);
var data = buffer[..received];
var response = new Response(data);
AddToCache(response);
return response;
}
catch (SocketException) { /* next server/attempt */ }
}
return new Response { ErrorMessage = "Timeout Error" };
}
private async Task<Response> TcpRequestAsync(IPEndPoint server, Request request)
{
Memory<byte> data = request.Data;
for (int attempt = 0; attempt < retries; attempt++)
{
using var client = new TcpClient(server.AddressFamily);
client.ReceiveTimeout = timeoutSeconds * 1000;
client.SendTimeout = timeoutSeconds * 1000;
try
{
await client.ConnectAsync(server.Address, server.Port);
await using var stream = client.GetStream();
// 2-byte length prefix (big-endian) – zonder WriteByteAsync
byte[] lengthPrefix = [(byte)(data.Length >> 8), (byte)(data.Length & 0xFF)];
await stream.WriteAsync(lengthPrefix);
await stream.WriteAsync(data.ToArray());
await stream.FlushAsync();
// lees 2-byte length prefix
byte[] lengthBuffer = new byte[2];
await stream.ReadExactlyAsync(lengthBuffer);
int length = (lengthBuffer[0] << 8) | lengthBuffer[1];
// lees het echte DNS-bericht
byte[] responseData = new byte[length];
await stream.ReadExactlyAsync(responseData);
Response response = new(responseData);
AddToCache(response);
return response;
}
catch (Exception)
{
// volgende server / poging
}
}
return new Response { ErrorMessage = "Timeout Error" };
}
}