diff --git a/src/pdns-dhcp/PowerDns/Methods.cs b/src/pdns-dhcp/PowerDns/Methods.cs index d6843f8..acce31c 100644 --- a/src/pdns-dhcp/PowerDns/Methods.cs +++ b/src/pdns-dhcp/PowerDns/Methods.cs @@ -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 ExtensionData { get; } = []; -} +public class Method; -public abstract class Method : Method where TSelf : Method, IMethod; +[JsonSerializable(typeof(Method)), JsonSourceGenerationOptions( + GenerationMode = JsonSourceGenerationMode.Metadata, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + UseStringEnumConverter = true +)] +internal partial class MethodContext : JsonSerializerContext; -public abstract class Method(TParam parameters) : Method where TSelf : Method, IMethod +public abstract class Method(TParam parameters) : Method + where TParam : MethodParameters { public TParam Parameters => parameters; } -public class InitializeMethod : Method, IMethod; +public class InitializeMethod(InitializeMethodParameters parameters) : Method(parameters), IMethod; -public class LookupMethod : Method, IMethod; +public class LookupMethod(LookupMethodParameters parameters) : Method(parameters), IMethod; diff --git a/src/pdns-dhcp/PowerDns/Parameters.cs b/src/pdns-dhcp/PowerDns/Parameters.cs new file mode 100644 index 0000000..8e480c7 --- /dev/null +++ b/src/pdns-dhcp/PowerDns/Parameters.cs @@ -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 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; diff --git a/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs b/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs index 02dac61..861506b 100644 --- a/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs +++ b/src/pdns-dhcp/PowerDns/PowerDnsHandler.cs @@ -15,6 +15,7 @@ public class PowerDnsHandler : ConnectionHandler JsonReaderState state = default; using ArrayPoolBufferWriter json = new(); using ArrayPoolBufferWriter 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(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 Handle(Method method, CancellationToken cancellationToken = default) + { + return method switch + { + InitializeMethod init => HandleInitializeMethod(init), + LookupMethod lookup => HandleLookupMethod(lookup), + + _ => ValueTask.FromResult(new BoolReply(false)) + }; + } + + private ValueTask HandleInitializeMethod(InitializeMethod method) + { + return ValueTask.FromResult(BoolReply.True); + } + + private ValueTask HandleLookupMethod(LookupMethod method) + { + return ValueTask.FromResult(BoolReply.False); + } } diff --git a/src/pdns-dhcp/PowerDns/Replies.cs b/src/pdns-dhcp/PowerDns/Replies.cs index 0d271cd..c1ea16a 100644 --- a/src/pdns-dhcp/PowerDns/Replies.cs +++ b/src/pdns-dhcp/PowerDns/Replies.cs @@ -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 result) : Reply { public T Result => result; } -public class BoolReply(bool result) : Reply(result); +public class BoolReply(bool result) : Reply(result) +{ + public static Reply False { get; } = new BoolReply(false); + + public static Reply True { get; } = new BoolReply(true); +} + +public class LookupReply(QueryResult[] result) : Reply(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; +}