System.Text.Json deserialization is incompatible with this usage
This commit is contained in:
parent
af6a02b6dc
commit
854b51b46b
3 changed files with 77 additions and 29 deletions
|
|
@ -1,21 +1,12 @@
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace pdns_dhcp.PowerDns;
|
namespace pdns_dhcp.PowerDns;
|
||||||
|
|
||||||
public interface IMethod;
|
public interface IMethod;
|
||||||
|
|
||||||
[JsonPolymorphic(TypeDiscriminatorPropertyName = "method")]
|
public record MethodBase(string Method);
|
||||||
[JsonDerivedType(typeof(InitializeMethod), "initialize")]
|
|
||||||
[JsonDerivedType(typeof(LookupMethod), "lookup")]
|
|
||||||
public class Method;
|
|
||||||
|
|
||||||
public abstract class Method<TParam>(TParam parameters) : Method
|
public abstract record Method<TParam>(string Method, TParam Parameters) : MethodBase(Method)
|
||||||
where TParam : MethodParameters
|
where TParam : MethodParameters;
|
||||||
{
|
|
||||||
[JsonPropertyName("parameters")]
|
|
||||||
public TParam Parameters => parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class InitializeMethod(InitializeParameters parameters) : Method<InitializeParameters>(parameters), IMethod;
|
public record InitializeMethod(InitializeParameters Parameters) : Method<InitializeParameters>("initialize", Parameters), IMethod;
|
||||||
|
|
||||||
public class LookupMethod(LookupParameters parameters) : Method<LookupParameters>(parameters), IMethod;
|
public record LookupMethod(LookupParameters Parameters) : Method<LookupParameters>("lookup", Parameters), IMethod;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.IO.Pipelines;
|
using System.IO.Pipelines;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
|
@ -15,9 +16,34 @@ namespace pdns_dhcp.PowerDns;
|
||||||
|
|
||||||
public class PowerDnsHandler : ConnectionHandler
|
public class PowerDnsHandler : ConnectionHandler
|
||||||
{
|
{
|
||||||
|
delegate MethodBase? HandlerConverter(in JsonElement element);
|
||||||
|
|
||||||
|
private static readonly ReadOnlyDictionary<string, HandlerConverter> Converters;
|
||||||
|
|
||||||
private readonly ILogger<PowerDnsHandler> _logger;
|
private readonly ILogger<PowerDnsHandler> _logger;
|
||||||
private readonly DnsRepository _repository;
|
private readonly DnsRepository _repository;
|
||||||
|
|
||||||
|
static PowerDnsHandler()
|
||||||
|
{
|
||||||
|
Dictionary<string, HandlerConverter> converters = new(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
["initialize"] = ToInitialize,
|
||||||
|
["lookup"] = ToLookup
|
||||||
|
};
|
||||||
|
|
||||||
|
Converters = converters.AsReadOnly();
|
||||||
|
|
||||||
|
static InitializeMethod ToInitialize(in JsonElement element)
|
||||||
|
{
|
||||||
|
return new(element.Deserialize(PowerDnsSerializerContext.Default.InitializeParameters)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LookupMethod ToLookup(in JsonElement element)
|
||||||
|
{
|
||||||
|
return new(element.Deserialize(PowerDnsSerializerContext.Default.LookupParameters)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public PowerDnsHandler(DnsRepository repository, ILogger<PowerDnsHandler> logger)
|
public PowerDnsHandler(DnsRepository repository, ILogger<PowerDnsHandler> logger)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
|
@ -41,22 +67,43 @@ public class PowerDnsHandler : ConnectionHandler
|
||||||
foreach (var memory in read.Buffer)
|
foreach (var memory in read.Buffer)
|
||||||
{
|
{
|
||||||
buffer.Write(memory.Span);
|
buffer.Write(memory.Span);
|
||||||
if (ConsumeJson(buffer, json, ref state))
|
if (!ConsumeJson(buffer, json, ref state))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodBase method;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var jsonDocument = JsonDocument.Parse(json.WrittenMemory);
|
||||||
|
var root = jsonDocument.RootElement;
|
||||||
|
if (!root.TryGetProperty("method", out var methodElement))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Parse(methodElement, root.GetProperty("parameters")) is not { } methodLocal)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
method = methodLocal;
|
||||||
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
var method = JsonSerializer.Deserialize(json.WrittenSpan, PowerDnsSerializerContext.Default.Method)!;
|
|
||||||
json.Clear();
|
json.Clear();
|
||||||
state = default;
|
state = default;
|
||||||
|
|
||||||
Reply reply = BoolReply.False;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
reply = await Handle(method, connection.ConnectionClosed).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception e) { }
|
|
||||||
|
|
||||||
await JsonSerializer.SerializeAsync(writer, reply, PowerDnsSerializerContext.Default.Reply, connection.ConnectionClosed)
|
|
||||||
.ConfigureAwait(continueOnCapturedContext: false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reply reply = BoolReply.False;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
reply = await Handle(method, connection.ConnectionClosed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception e) { }
|
||||||
|
|
||||||
|
await JsonSerializer.SerializeAsync(writer, reply, PowerDnsSerializerContext.Default.Reply, connection.ConnectionClosed)
|
||||||
|
.ConfigureAwait(continueOnCapturedContext: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
input.AdvanceTo(read.Buffer.End);
|
input.AdvanceTo(read.Buffer.End);
|
||||||
|
|
@ -111,9 +158,20 @@ public class PowerDnsHandler : ConnectionHandler
|
||||||
|
|
||||||
return final;
|
return final;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MethodBase? Parse(in JsonElement element, in JsonElement parameters)
|
||||||
|
{
|
||||||
|
HandlerConverter? converter = default;
|
||||||
|
return element.GetString() switch
|
||||||
|
{
|
||||||
|
null => null,
|
||||||
|
{ } methodName when !Converters.TryGetValue(methodName, out converter) => new MethodBase(methodName),
|
||||||
|
_ => converter(parameters)
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueTask<Reply> Handle(Method method, CancellationToken cancellationToken = default)
|
private ValueTask<Reply> Handle(MethodBase method, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return method switch
|
return method switch
|
||||||
{
|
{
|
||||||
|
|
@ -123,7 +181,7 @@ public class PowerDnsHandler : ConnectionHandler
|
||||||
_ => LogUnhandled(_logger, method)
|
_ => LogUnhandled(_logger, method)
|
||||||
};
|
};
|
||||||
|
|
||||||
static ValueTask<Reply> LogUnhandled(ILogger logger, Method method)
|
static ValueTask<Reply> LogUnhandled(ILogger logger, MethodBase method)
|
||||||
{
|
{
|
||||||
logger.LogWarning("Unhandled Method {Method}", method);
|
logger.LogWarning("Unhandled Method {Method}", method);
|
||||||
return ValueTask.FromResult<Reply>(BoolReply.False);
|
return ValueTask.FromResult<Reply>(BoolReply.False);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ using System.Text.Json.Serialization;
|
||||||
namespace pdns_dhcp.PowerDns;
|
namespace pdns_dhcp.PowerDns;
|
||||||
|
|
||||||
[JsonSerializable(typeof(Reply))]
|
[JsonSerializable(typeof(Reply))]
|
||||||
[JsonSerializable(typeof(Method))]
|
|
||||||
[JsonSerializable(typeof(Parameters))]
|
[JsonSerializable(typeof(Parameters))]
|
||||||
[JsonSourceGenerationOptions(
|
[JsonSourceGenerationOptions(
|
||||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue