mirror of
https://github.com/netchx/netch.git
synced 2026-05-05 22:35:48 +08:00
done
This commit is contained in:
11
Netch/3rd/DNS/Client/RequestResolver/IRequestResolver.cs
Normal file
11
Netch/3rd/DNS/Client/RequestResolver/IRequestResolver.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using DNS.Protocol;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DNS.Client.RequestResolver
|
||||
{
|
||||
public interface IRequestResolver
|
||||
{
|
||||
Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default(CancellationToken));
|
||||
}
|
||||
}
|
||||
14
Netch/3rd/DNS/Client/RequestResolver/NullRequestResolver.cs
Normal file
14
Netch/3rd/DNS/Client/RequestResolver/NullRequestResolver.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using DNS.Protocol;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DNS.Client.RequestResolver
|
||||
{
|
||||
public class NullRequestResolver : IRequestResolver
|
||||
{
|
||||
public Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
throw new ResponseException("Request failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
72
Netch/3rd/DNS/Client/RequestResolver/TcpRequestResolver.cs
Normal file
72
Netch/3rd/DNS/Client/RequestResolver/TcpRequestResolver.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using DNS.Protocol;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DNS.Client.RequestResolver
|
||||
{
|
||||
public class TcpRequestResolver : IRequestResolver
|
||||
{
|
||||
private IPEndPoint dns;
|
||||
|
||||
public TcpRequestResolver(IPEndPoint dns)
|
||||
{
|
||||
this.dns = dns;
|
||||
}
|
||||
|
||||
public async Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
using (TcpClient tcp = new TcpClient())
|
||||
{
|
||||
await tcp.ConnectAsync(dns.Address, dns.Port);
|
||||
|
||||
Stream stream = tcp.GetStream();
|
||||
byte[] buffer = request.ToArray();
|
||||
byte[] length = BitConverter.GetBytes((ushort)buffer.Length);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(length);
|
||||
}
|
||||
|
||||
await stream.WriteAsync(length, 0, length.Length, cancellationToken);
|
||||
await stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken);
|
||||
|
||||
buffer = new byte[2];
|
||||
await Read(stream, buffer, cancellationToken);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
Array.Reverse(buffer);
|
||||
}
|
||||
|
||||
buffer = new byte[BitConverter.ToUInt16(buffer, 0)];
|
||||
await Read(stream, buffer, cancellationToken);
|
||||
|
||||
IResponse response = Response.FromArray(buffer);
|
||||
return new ClientResponse(request, response, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task Read(Stream stream, byte[] buffer, CancellationToken cancellationToken)
|
||||
{
|
||||
int length = buffer.Length;
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
while (length > 0 && (size = await stream.ReadAsync(buffer, offset, length, cancellationToken)) > 0)
|
||||
{
|
||||
offset += size;
|
||||
length -= size;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
throw new IOException("Unexpected end of stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
Netch/3rd/DNS/Client/RequestResolver/UdpRequestResolver.cs
Normal file
57
Netch/3rd/DNS/Client/RequestResolver/UdpRequestResolver.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using DNS.Protocol;
|
||||
using DNS.Protocol.Utils;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DNS.Client.RequestResolver
|
||||
{
|
||||
public class UdpRequestResolver : IRequestResolver
|
||||
{
|
||||
private int timeout;
|
||||
private IRequestResolver fallback;
|
||||
private IPEndPoint dns;
|
||||
|
||||
public UdpRequestResolver(IPEndPoint dns, IRequestResolver fallback, int timeout = 5000)
|
||||
{
|
||||
this.dns = dns;
|
||||
this.fallback = fallback;
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public UdpRequestResolver(IPEndPoint dns, int timeout = 5000)
|
||||
{
|
||||
this.dns = dns;
|
||||
this.fallback = new NullRequestResolver();
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public async Task<IResponse> Resolve(IRequest request, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
using (UdpClient udp = new UdpClient())
|
||||
{
|
||||
await udp
|
||||
.SendAsync(request.ToArray(), request.Size, dns)
|
||||
.WithCancellationTimeout(TimeSpan.FromMilliseconds(timeout), cancellationToken);
|
||||
|
||||
UdpReceiveResult result = await udp
|
||||
.ReceiveAsync()
|
||||
.WithCancellationTimeout(TimeSpan.FromMilliseconds(timeout), cancellationToken);
|
||||
|
||||
if (!result.RemoteEndPoint.Equals(dns)) throw new IOException("Remote endpoint mismatch");
|
||||
byte[] buffer = result.Buffer;
|
||||
Response response = Response.FromArray(buffer);
|
||||
|
||||
if (response.Truncated)
|
||||
{
|
||||
return await fallback.Resolve(request, cancellationToken);
|
||||
}
|
||||
|
||||
return new ClientResponse(request, response, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user