milestone 7: serving pipeline, client tracking, pause and lifecycle

This commit is contained in:
2026-08-01 21:43:52 +02:00
parent 8c50b6617f
commit a8092bb1b9
17 changed files with 5916 additions and 131 deletions
+33 -4
View File
@@ -14,6 +14,10 @@ const net = std.Io.net;
const handler = @import("handler.zig");
const udp_server = @import("udp_server.zig");
const model = @import("../config/model.zig");
const response = @import("../filter/response.zig");
const forward_zones = @import("../local/forward_zones.zig");
const records = @import("../local/records.zig");
const header = @import("../dns/header.zig");
const packet = @import("../dns/packet.zig");
const types = @import("../dns/types.zig");
@@ -21,6 +25,31 @@ const transport = @import("../upstream/transport.zig");
const testing = std.testing;
const empty_records: records.Records = .empty;
const empty_zones: forward_zones.Zones = .empty;
const blocking_defaults: model.Blocking = .{};
const blocking: response.Options = .{
.mode = blocking_defaults.response,
.ttl = blocking_defaults.ttl,
};
const forward_timeout: std.Io.Clock.Duration = .{
.raw = model.readTimeout(.{}),
.clock = .awake,
};
/// An upstream and nothing else optional: no filtering, no cache, no log. The
/// listener is what these tests exercise, so the handler is the same bare one
/// its own tests use.
fn bareHandler(client: transport.Client) handler.Handler {
return .{
.upstream = client,
.blocking = blocking,
.forward_read_timeout = forward_timeout,
.records = &empty_records,
.zones = &empty_zones,
};
}
/// Long enough that a loopback round trip cannot lose to scheduling, short
/// enough that a broken server fails the run instead of hanging it.
const budget: std.Io.Timeout = .{ .duration = .{ .raw = .fromSeconds(5), .clock = .awake } };
@@ -87,7 +116,7 @@ test "a udp query is answered on the loopback" {
const io = threaded.io();
var fake: FakeUpstream = .{ .reply = response_bytes };
var h: handler.Handler = .{ .upstream = fake.client() };
var h = bareHandler(fake.client());
const listen_address: net.IpAddress = try .parse("127.0.0.1", 0);
var server = try udp_server.UdpServer.bind(gpa, io, listen_address, &h, .{ .max_in_flight = 4 });
@@ -125,7 +154,7 @@ test "a runt datagram is dropped and no reply is sent" {
const io = threaded.io();
var fake: FakeUpstream = .{ .reply = response_bytes };
var h: handler.Handler = .{ .upstream = fake.client() };
var h = bareHandler(fake.client());
const listen_address: net.IpAddress = try .parse("127.0.0.1", 0);
var server = try udp_server.UdpServer.bind(gpa, io, listen_address, &h, .{ .max_in_flight = 4 });
@@ -160,7 +189,7 @@ test "an oversize datagram arrives truncated and is dropped" {
const io = threaded.io();
var fake: FakeUpstream = .{ .reply = response_bytes };
var h: handler.Handler = .{ .upstream = fake.client() };
var h = bareHandler(fake.client());
const listen_address: net.IpAddress = try .parse("127.0.0.1", 0);
var server = try udp_server.UdpServer.bind(gpa, io, listen_address, &h, .{ .max_in_flight = 4 });
@@ -201,7 +230,7 @@ test "deinit ends a serve loop that is blocked on receive" {
const io = threaded.io();
var fake: FakeUpstream = .{ .reply = response_bytes };
var h: handler.Handler = .{ .upstream = fake.client() };
var h = bareHandler(fake.client());
const listen_address: net.IpAddress = try .parse("127.0.0.1", 0);
var server = try udp_server.UdpServer.bind(gpa, io, listen_address, &h, .{ .max_in_flight = 4 });