Port to Kestrel
This commit is contained in:
parent
7f9dc36473
commit
5c9db5d5f2
6 changed files with 76 additions and 114 deletions
11
src/pdns-dhcp/Connections/ProtocolSocketIPEndPoint.cs
Normal file
11
src/pdns-dhcp/Connections/ProtocolSocketIPEndPoint.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace pdns_dhcp.Connections;
|
||||||
|
|
||||||
|
public class ProtocolSocketIPEndPoint(IPAddress address, int port, ProtocolType protocolType, SocketType socketType) : IPEndPoint(address, port)
|
||||||
|
{
|
||||||
|
public ProtocolType ProtocolType => protocolType;
|
||||||
|
|
||||||
|
public SocketType SocketType => socketType;
|
||||||
|
}
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
using Stl.Interception;
|
|
||||||
|
|
||||||
namespace pdns_dhcp.PowerDns;
|
|
||||||
|
|
||||||
public interface IPowerDnsFactory : IRequiresFullProxy
|
|
||||||
{
|
|
||||||
PowerDnsStreamClient CreateClient(Stream stream);
|
|
||||||
}
|
|
||||||
11
src/pdns-dhcp/PowerDns/PowerDnsHandler.cs
Normal file
11
src/pdns-dhcp/PowerDns/PowerDnsHandler.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
|
||||||
|
namespace pdns_dhcp.PowerDns;
|
||||||
|
|
||||||
|
public class PowerDnsHandler : ConnectionHandler
|
||||||
|
{
|
||||||
|
public override Task OnConnectedAsync(ConnectionContext connection)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace pdns_dhcp.PowerDns;
|
|
||||||
|
|
||||||
public class PowerDnsStreamClient : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Stream _stream;
|
|
||||||
private CancellationTokenSource _cts = new();
|
|
||||||
private Task _task;
|
|
||||||
|
|
||||||
public PowerDnsStreamClient(Stream stream)
|
|
||||||
{
|
|
||||||
_stream = stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
~PowerDnsStreamClient()
|
|
||||||
{
|
|
||||||
DisposeCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_cts.Cancel();
|
|
||||||
if (Interlocked.Exchange(ref _task, null!) is { } task)
|
|
||||||
{
|
|
||||||
task
|
|
||||||
.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing)
|
|
||||||
.GetAwaiter().GetResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
DisposeCore();
|
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Start(CancellationToken stoppingToken)
|
|
||||||
{
|
|
||||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken);
|
|
||||||
using var old = Interlocked.Exchange(ref _cts, cts);
|
|
||||||
old.Cancel();
|
|
||||||
_task = Run(cts.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DisposeCore()
|
|
||||||
{
|
|
||||||
_cts.Dispose();
|
|
||||||
_stream.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task Run(CancellationToken stoppingToken)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
switch (await JsonSerializer.DeserializeAsync<Method>(_stream, cancellationToken: stoppingToken).ConfigureAwait(false))
|
|
||||||
{
|
|
||||||
case InitializeMethod init:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case LookupMethod lookup:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (Interlocked.Exchange(ref _task, null!) is not null)
|
|
||||||
{
|
|
||||||
Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,14 @@
|
||||||
using Microsoft.AspNetCore.Builder;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Connections;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
using pdns_dhcp.Connections;
|
||||||
using pdns_dhcp.Kea;
|
using pdns_dhcp.Kea;
|
||||||
using pdns_dhcp.Options;
|
using pdns_dhcp.Options;
|
||||||
using pdns_dhcp.PowerDns;
|
using pdns_dhcp.PowerDns;
|
||||||
|
|
@ -10,6 +17,7 @@ using pdns_dhcp.Services;
|
||||||
using Stl.Interception;
|
using Stl.Interception;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
builder.Services.Configure<DhcpOptions>(builder.Configuration.GetRequiredSection("Dhcp"));
|
builder.Services.Configure<DhcpOptions>(builder.Configuration.GetRequiredSection("Dhcp"));
|
||||||
builder.Services.Configure<PowerDnsOptions>(builder.Configuration.GetRequiredSection("PowerDns"));
|
builder.Services.Configure<PowerDnsOptions>(builder.Configuration.GetRequiredSection("PowerDns"));
|
||||||
|
|
||||||
|
|
@ -17,9 +25,50 @@ builder.Services.AddHostedService<DhcpLeaseWatcher>();
|
||||||
builder.Services.AddHostedService<PowerDnsBackend>();
|
builder.Services.AddHostedService<PowerDnsBackend>();
|
||||||
|
|
||||||
builder.Services.AddTypedFactory<IDhcpLeaseWatcherFactory>();
|
builder.Services.AddTypedFactory<IDhcpLeaseWatcherFactory>();
|
||||||
builder.Services.AddTypedFactory<IPowerDnsFactory>();
|
|
||||||
|
|
||||||
builder.Services.AddTransient<KeaDhcp4LeaseHandler>();
|
builder.Services.AddTransient<KeaDhcp4LeaseHandler>();
|
||||||
builder.Services.AddTransient<KeaDhcp6LeaseHandler>();
|
builder.Services.AddTransient<KeaDhcp6LeaseHandler>();
|
||||||
|
|
||||||
|
builder.WebHost.UseSockets(options =>
|
||||||
|
{
|
||||||
|
options.CreateBoundListenSocket = endpoint =>
|
||||||
|
{
|
||||||
|
Socket socket;
|
||||||
|
switch (endpoint)
|
||||||
|
{
|
||||||
|
case ProtocolSocketIPEndPoint socketIp:
|
||||||
|
socket = new Socket(socketIp.AddressFamily, socketIp.SocketType, socketIp.ProtocolType);
|
||||||
|
|
||||||
|
if (socketIp.Address.Equals(IPAddress.IPv6Any))
|
||||||
|
{
|
||||||
|
socket.DualMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return SocketTransportOptions.CreateDefaultBoundListenSocket(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.Bind(endpoint);
|
||||||
|
return socket;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.WebHost.UseKestrelCore();
|
||||||
|
builder.WebHost.ConfigureKestrel((context, options) =>
|
||||||
|
{
|
||||||
|
if (context.Configuration.GetRequiredSection("PowerDns:Listener").Get<PowerDnsListenerOptions>() is { } pdnsOptions)
|
||||||
|
{
|
||||||
|
var path = PathEx.ExpandPath(pdnsOptions.Socket);
|
||||||
|
FileInfo file = new(path);
|
||||||
|
file.Directory!.Create();
|
||||||
|
file.Delete();
|
||||||
|
options.ListenUnixSocket(path, options =>
|
||||||
|
{
|
||||||
|
options.UseConnectionHandler<PowerDnsHandler>();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
builder.Build().Run();
|
builder.Build().Run();
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,11 @@
|
||||||
using System.Net.Sockets;
|
|
||||||
|
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
|
|
||||||
using pdns_dhcp.Options;
|
|
||||||
using pdns_dhcp.PowerDns;
|
|
||||||
|
|
||||||
namespace pdns_dhcp.Services;
|
namespace pdns_dhcp.Services;
|
||||||
|
|
||||||
public class PowerDnsBackend : BackgroundService
|
public class PowerDnsBackend : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly IPowerDnsFactory _factory;
|
public PowerDnsBackend()
|
||||||
private readonly Socket _socket;
|
|
||||||
|
|
||||||
public PowerDnsBackend(IOptions<PowerDnsOptions> options, IPowerDnsFactory socketFactory)
|
|
||||||
{
|
{
|
||||||
_factory = socketFactory;
|
|
||||||
_socket = new(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
|
|
||||||
var path = PathEx.ExpandPath(options.Value.Listener.Socket);
|
|
||||||
FileInfo file = new(path);
|
|
||||||
file.Directory!.Create();
|
|
||||||
file.Delete();
|
|
||||||
_socket.Bind(new UnixDomainSocketEndPoint(path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PowerDnsBackend()
|
~PowerDnsBackend()
|
||||||
|
|
@ -29,14 +13,9 @@ public class PowerDnsBackend : BackgroundService
|
||||||
DisposeCore();
|
DisposeCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||||
{
|
{
|
||||||
_socket.Listen();
|
return Task.CompletedTask;
|
||||||
while (await _socket.AcceptAsync(stoppingToken) is { } client)
|
|
||||||
{
|
|
||||||
_factory.CreateClient(new NetworkStream(client, true))
|
|
||||||
.Start(stoppingToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public override void Dispose()
|
||||||
|
|
@ -48,6 +27,5 @@ public class PowerDnsBackend : BackgroundService
|
||||||
|
|
||||||
private void DisposeCore()
|
private void DisposeCore()
|
||||||
{
|
{
|
||||||
_socket.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue