PowerDNS JSON handler

This commit is contained in:
Jöran Malek 2023-12-18 23:51:12 +01:00
parent a23049e449
commit d101277c9a
4 changed files with 107 additions and 12 deletions

View file

@ -1,4 +1,3 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace pdns_dhcp.PowerDns;
@ -8,19 +7,21 @@ public interface IMethod;
[JsonPolymorphic(TypeDiscriminatorPropertyName = "method")]
[JsonDerivedType(typeof(InitializeMethod), "initialize")]
[JsonDerivedType(typeof(LookupMethod), "lookup")]
public abstract class Method
{
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtensionData { get; } = [];
}
public class Method;
public abstract class Method<TSelf> : Method where TSelf : Method<TSelf>, IMethod;
[JsonSerializable(typeof(Method)), JsonSourceGenerationOptions(
GenerationMode = JsonSourceGenerationMode.Metadata,
NumberHandling = JsonNumberHandling.AllowReadingFromString,
UseStringEnumConverter = true
)]
internal partial class MethodContext : JsonSerializerContext;
public abstract class Method<TSelf, TParam>(TParam parameters) : Method<TSelf> where TSelf : Method<TSelf, TParam>, IMethod
public abstract class Method<TParam>(TParam parameters) : Method
where TParam : MethodParameters
{
public TParam Parameters => parameters;
}
public class InitializeMethod : Method<InitializeMethod>, IMethod;
public class InitializeMethod(InitializeMethodParameters parameters) : Method<InitializeMethodParameters>(parameters), IMethod;
public class LookupMethod : Method<LookupMethod>, IMethod;
public class LookupMethod(LookupMethodParameters parameters) : Method<LookupMethodParameters>(parameters), IMethod;

View file

@ -0,0 +1,26 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace pdns_dhcp.PowerDns;
public record class Parameters;
public record class MethodParameters : Parameters
{
[JsonExtensionData]
public Dictionary<string, JsonElement> AdditionalProperties { get; set; } = [];
}
public record class InitializeMethodParameters(
[property: JsonPropertyName("command")] string Command,
[property: JsonPropertyName("timeout")] int Timeout
) : MethodParameters;
public record class LookupMethodParameters(
[property: JsonPropertyName("qtype")] string Qtype,
[property: JsonPropertyName("qname")] string Qname,
[property: JsonPropertyName("remote")] string Remote,
[property: JsonPropertyName("local")] string Local,
[property: JsonPropertyName("real-remote")] string RealRemote,
[property: JsonPropertyName("zone-id")] int ZoneId
) : MethodParameters;

View file

@ -15,6 +15,7 @@ public class PowerDnsHandler : ConnectionHandler
JsonReaderState state = default;
using ArrayPoolBufferWriter<byte> json = new();
using ArrayPoolBufferWriter<byte> buffer = new();
using var writer = connection.Transport.Output.AsStream();
while (!connection.ConnectionClosed.IsCancellationRequested)
{
var read = await input.ReadAsync(connection.ConnectionClosed).ConfigureAwait(false);
@ -28,9 +29,19 @@ public class PowerDnsHandler : ConnectionHandler
buffer.Write(memory.Span);
if (ConsumeJson(buffer, json, ref state))
{
var method = JsonSerializer.Deserialize<Method>(json.WrittenSpan);
var method = JsonSerializer.Deserialize(json.WrittenSpan, MethodContext.Default.Method)!;
json.Clear();
state = default;
Reply reply = BoolReply.False;
try
{
reply = await Handle(method, connection.ConnectionClosed).ConfigureAwait(false);
}
catch (Exception e) { }
await JsonSerializer.SerializeAsync(writer, reply, ReplyContext.Default.Reply, connection.ConnectionClosed)
.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing);
}
}
@ -75,4 +86,25 @@ public class PowerDnsHandler : ConnectionHandler
return final;
}
}
private ValueTask<Reply> Handle(Method method, CancellationToken cancellationToken = default)
{
return method switch
{
InitializeMethod init => HandleInitializeMethod(init),
LookupMethod lookup => HandleLookupMethod(lookup),
_ => ValueTask.FromResult<Reply>(new BoolReply(false))
};
}
private ValueTask<Reply> HandleInitializeMethod(InitializeMethod method)
{
return ValueTask.FromResult(BoolReply.True);
}
private ValueTask<Reply> HandleLookupMethod(LookupMethod method)
{
return ValueTask.FromResult(BoolReply.False);
}
}

View file

@ -1,10 +1,46 @@
using System.Text.Json;
using System.Text.Json.Serialization;
namespace pdns_dhcp.PowerDns;
[JsonDerivedType(typeof(BoolReply))]
[JsonDerivedType(typeof(LookupReply))]
public abstract class Reply;
[JsonSerializable(typeof(Reply)), JsonSourceGenerationOptions(
GenerationMode = JsonSourceGenerationMode.Serialization,
PropertyNamingPolicy = JsonKnownNamingPolicy.KebabCaseLower,
WriteIndented = false
)]
internal partial class ReplyContext : JsonSerializerContext;
public abstract class Reply<T>(T result) : Reply
{
public T Result => result;
}
public class BoolReply(bool result) : Reply<bool>(result);
public class BoolReply(bool result) : Reply<bool>(result)
{
public static Reply False { get; } = new BoolReply(false);
public static Reply True { get; } = new BoolReply(true);
}
public class LookupReply(QueryResult[] result) : Reply<QueryResult[]>(result);
public record QueryResult(
[property: JsonPropertyName("qtype")] string QType,
[property: JsonPropertyName("qname")] string QName,
[property: JsonPropertyName("content")] string Content,
[property: JsonPropertyName("ttl")] int TTL
)
{
[JsonPropertyName("auth")]
public bool? Auth { get; init; } = default;
[JsonPropertyName("domain_id")]
public int? DomainId { get; init; } = default;
[JsonPropertyName("scopeMask")]
public int? ScopeMask { get; init; } = default;
}