milestone 18: collapse duplicated infrastructure into shared listener core, crud list helper, resource shells, transport race, name and line helpers, ui modules
This commit is contained in:
+19
-39
@@ -179,9 +179,9 @@ pub const DotClient = struct {
|
||||
|
||||
var stream = address.connect(io, .{ .mode = .stream }) catch |err| {
|
||||
log.debug("{f}", .{self.diagnose(.{ .connect_failed = err })});
|
||||
return mapPhase(err, error.ConnectFailed);
|
||||
return transport.mapPhase(err, error.ConnectFailed);
|
||||
};
|
||||
defer closeStream(io, &stream);
|
||||
defer transport.closeBlocked(io, &stream);
|
||||
|
||||
// `TlsStream` is pinned: it holds its reader and writer by value and the
|
||||
// TLS client points at them, so it must not move after `init`.
|
||||
@@ -205,9 +205,9 @@ pub const DotClient = struct {
|
||||
.verify_name = self.verify_name,
|
||||
.cause = cause,
|
||||
} })});
|
||||
return mapPhase(cause, error.TlsFailed);
|
||||
return transport.mapPhase(cause, error.TlsFailed);
|
||||
};
|
||||
defer closeTls(io, &tls_stream);
|
||||
defer transport.closeBlocked(io, &tls_stream);
|
||||
|
||||
const writer = tls_stream.writer();
|
||||
const prefix = transport.framePrefix(@intCast(query.len));
|
||||
@@ -241,7 +241,7 @@ pub const DotClient = struct {
|
||||
/// cancellation into `error.CertificateBundleLoadFailure`. That name cannot
|
||||
/// tell an `error.OutOfMemory` from a corrupt PEM file, and the first is a
|
||||
/// local resource failure that must not count against the upstream's
|
||||
/// health. Scanning here keeps the concrete error for `mapPhase`.
|
||||
/// health. Scanning here keeps the concrete error for `transport.mapPhase`.
|
||||
fn ensureBundle(self: *DotClient, io: std.Io) transport.ExchangeError!void {
|
||||
{
|
||||
try self.bundle_lock.lockShared(io);
|
||||
@@ -259,31 +259,11 @@ pub const DotClient = struct {
|
||||
self.bundle.deinit(self.gpa);
|
||||
self.bundle.* = .empty;
|
||||
log.warn("{f}", .{self.diagnose(.{ .bundle_load_failed = err })});
|
||||
return mapPhase(err, error.TlsFailed);
|
||||
return transport.mapPhase(err, error.TlsFailed);
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// The pool cancels this task when the attempt budget expires. The next
|
||||
/// cancelable `Io` call in the `defer` chain would then return `error.Canceled`
|
||||
/// and skip the close, leaking the socket, so the close runs with cancellation
|
||||
/// blocked.
|
||||
fn closeStream(io: std.Io, stream: *net.Stream) void {
|
||||
const prev = io.swapCancelProtection(.blocked);
|
||||
defer _ = io.swapCancelProtection(prev);
|
||||
stream.close(io);
|
||||
}
|
||||
|
||||
fn closeTls(io: std.Io, stream: *tls_client.TlsStream) void {
|
||||
const prev = io.swapCancelProtection(.blocked);
|
||||
defer _ = io.swapCancelProtection(prev);
|
||||
stream.close();
|
||||
}
|
||||
|
||||
fn mapPhase(err: anyerror, phase: transport.PeerFault) transport.ExchangeError {
|
||||
return transport.mapLocal(err) orelse phase;
|
||||
}
|
||||
|
||||
/// The handshake reads and writes through the socket reader and writer, so a
|
||||
/// cancelled or resource-starved handshake surfaces as `error.ReadFailed` /
|
||||
/// `error.WriteFailed` with the cause stashed on those two. Without this,
|
||||
@@ -318,11 +298,11 @@ fn concreteWrite(stream: *tls_client.TlsStream, err: anyerror) anyerror {
|
||||
}
|
||||
|
||||
fn sendFailure(stream: *tls_client.TlsStream, err: anyerror) transport.ExchangeError {
|
||||
return mapPhase(concreteWrite(stream, err), error.SendFailed);
|
||||
return transport.mapPhase(concreteWrite(stream, err), error.SendFailed);
|
||||
}
|
||||
|
||||
fn receiveFailure(stream: *tls_client.TlsStream, err: anyerror) transport.ExchangeError {
|
||||
return mapPhase(concreteRead(stream, err), error.ReceiveFailed);
|
||||
return transport.mapPhase(concreteRead(stream, err), error.ReceiveFailed);
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
@@ -460,14 +440,14 @@ fn stubStream(
|
||||
|
||||
test "the handshake unwrap keeps a cancelled read out of the peer fault group" {
|
||||
var stream = stubStream(error.Canceled, null, null);
|
||||
const mapped = mapPhase(concreteHandshake(&stream, error.ReadFailed), error.TlsFailed);
|
||||
const mapped = transport.mapPhase(concreteHandshake(&stream, error.ReadFailed), error.TlsFailed);
|
||||
try testing.expectEqual(transport.ExchangeError.Canceled, mapped);
|
||||
try testing.expectEqual(transport.Group.cancellation, transport.group(mapped));
|
||||
}
|
||||
|
||||
test "the handshake unwrap keeps a local resource write failure out of the peer fault group" {
|
||||
var stream = stubStream(null, error.SystemResources, null);
|
||||
const mapped = mapPhase(concreteHandshake(&stream, error.WriteFailed), error.TlsFailed);
|
||||
const mapped = transport.mapPhase(concreteHandshake(&stream, error.WriteFailed), error.TlsFailed);
|
||||
try testing.expectEqual(transport.ExchangeError.SystemResources, mapped);
|
||||
try testing.expectEqual(transport.Group.local_resource, transport.group(mapped));
|
||||
}
|
||||
@@ -476,13 +456,13 @@ test "the handshake unwrap reports a peer side cause as a TLS fault" {
|
||||
var reset = stubStream(error.ConnectionResetByPeer, null, null);
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(concreteHandshake(&reset, error.ReadFailed), error.TlsFailed),
|
||||
transport.mapPhase(concreteHandshake(&reset, error.ReadFailed), error.TlsFailed),
|
||||
);
|
||||
|
||||
var refused = stubStream(null, error.ConnectionRefused, null);
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(concreteHandshake(&refused, error.WriteFailed), error.TlsFailed),
|
||||
transport.mapPhase(concreteHandshake(&refused, error.WriteFailed), error.TlsFailed),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -492,7 +472,7 @@ test "the handshake unwrap reports a TLS fault when no cause was stored" {
|
||||
try testing.expectEqual(error.WriteFailed, concreteHandshake(&stream, error.WriteFailed));
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(concreteHandshake(&stream, error.ReadFailed), error.TlsFailed),
|
||||
transport.mapPhase(concreteHandshake(&stream, error.ReadFailed), error.TlsFailed),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -505,11 +485,11 @@ test "the handshake unwrap passes other errors through untouched" {
|
||||
try testing.expectEqual(error.Canceled, concreteHandshake(&stream, error.Canceled));
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(concreteHandshake(&stream, error.CertificateExpired), error.TlsFailed),
|
||||
transport.mapPhase(concreteHandshake(&stream, error.CertificateExpired), error.TlsFailed),
|
||||
);
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.Canceled,
|
||||
mapPhase(concreteHandshake(&stream, error.Canceled), error.TlsFailed),
|
||||
transport.mapPhase(concreteHandshake(&stream, error.Canceled), error.TlsFailed),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -547,24 +527,24 @@ test "a CA bundle scan failure keeps local resource errors out of the peer fault
|
||||
for (local) |err| {
|
||||
try testing.expectEqual(
|
||||
transport.Group.local_resource,
|
||||
transport.group(mapPhase(err, error.TlsFailed)),
|
||||
transport.group(transport.mapPhase(err, error.TlsFailed)),
|
||||
);
|
||||
}
|
||||
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.Canceled,
|
||||
mapPhase(error.Canceled, error.TlsFailed),
|
||||
transport.mapPhase(error.Canceled, error.TlsFailed),
|
||||
);
|
||||
|
||||
// A missing or corrupt bundle is not this process running out of anything,
|
||||
// so it stays a TLS fault.
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(error.FileNotFound, error.TlsFailed),
|
||||
transport.mapPhase(error.FileNotFound, error.TlsFailed),
|
||||
);
|
||||
try testing.expectEqual(
|
||||
transport.ExchangeError.TlsFailed,
|
||||
mapPhase(error.MissingEndCertificateMarker, error.TlsFailed),
|
||||
transport.mapPhase(error.MissingEndCertificateMarker, error.TlsFailed),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user