mux: thread halt into live AACS key-map resolution; cover Session arm
Round-2 follow-ups to 6d6e60f (inline base-map resolve on the live
single-pass Session/Live mux arms).
Fix 1 (halt threading) — the inline resolve chain sampled ciphertext off
the LIVE drive with no cancel token, so an operator /api/stop during key
resolution was not honored (the FMTS probe can issue hundreds of reads,
each able to stall to the 60s SCSI recovery timeout — violating the
"don't hammer a struggling live drive" rule). Add an optional
`halt: Option<&Halt>` to `resolve_mux_key_map`, `resolve_fmts_key_map`,
`resolve_inline_base_map`, and `Disc::resolve_content_key_map`, and poll
it at each loop boundary (FMTS anchor + per-index probe loops, multi-CPS
extent loop) — returning Err(Halted) promptly. Live/Session arms pass the
driver's halt; sweep/patch pass their own token (via Halt::from_arc);
file-backed probe/ISO callers pass None. Tested with a pre-cancelled halt
(Err Halted, no extent sampling) and a None-halt no-abort case;
mutation-verified (dropping the extent-loop check → Ok, not Err).
Fix 2 (Session-arm coverage) — the MuxInput::Session arm ran the same
resolve→install→decrypt sequence as Live but had NO end-to-end test
(DiscSession only exposed open(), which needs live hardware). Add a
#[cfg(test)] DiscSession::from_parts_for_test (injected reader + scanned
disc, no Drive), an end-to-end AACS decrypt test through the Session arm
(mutation-verified: dropping with_key_map → mux aborts), and a
missing-reader clean-error (not panic) test.
Fix 3 (cleanups) — io_error_code: remove the unreachable typed-Error
downcast branch (From<Error> for io::Error stringifies; no path builds an
io::Error holding a typed Error), keeping the stringify parse is_halt /
is_skippable_title_stub rely on. Add a resolve_keys_for test covering the
largest-title sampling branch. Document the patch wedge-exit coverage gap
(TODO) in passn_handler_ab.rs.
This commit is contained in:
+1
-1
@@ -217,7 +217,7 @@ impl Disc {
|
||||
))
|
||||
}
|
||||
DecryptKeys::Aacs { .. } => Some(std::sync::Arc::new(
|
||||
self.resolve_content_key_map(reader, &mut base_keys, None)?,
|
||||
self.resolve_content_key_map(reader, &mut base_keys, None, opts.halt.as_ref())?,
|
||||
)),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
+11
-2
@@ -2401,11 +2401,18 @@ impl Disc {
|
||||
reader: &mut dyn SectorSource,
|
||||
keys: &mut crate::decrypt::DecryptKeys,
|
||||
fetch: Option<&crate::sector::KeyFetch>,
|
||||
halt: Option<&crate::halt::Halt>,
|
||||
) -> Result<crate::decrypt::AacsKeyMap> {
|
||||
let mut ranges: Vec<(u32, u32, usize, crate::decrypt::Phase)> = Vec::new();
|
||||
for title in &self.titles {
|
||||
let map =
|
||||
crate::mux::resolve_mux_key_map(reader, title, keys, fetch, self.content_format)?;
|
||||
let map = crate::mux::resolve_mux_key_map(
|
||||
reader,
|
||||
title,
|
||||
keys,
|
||||
fetch,
|
||||
self.content_format,
|
||||
halt,
|
||||
)?;
|
||||
ranges.extend_from_slice(map.ranges());
|
||||
}
|
||||
Ok(crate::decrypt::AacsKeyMap::from_ranges_phased(
|
||||
@@ -3206,10 +3213,12 @@ impl Disc {
|
||||
// separate content gate is needed. CSS keeps the content-gated
|
||||
// self-descramble path (the map path is AACS-only).
|
||||
let key_map = if opts.decrypt && decrypt_is_aacs {
|
||||
let halt = opts.halt.clone().map(crate::halt::Halt::from_arc);
|
||||
Some(std::sync::Arc::new(self.resolve_content_key_map(
|
||||
reader,
|
||||
&mut keys,
|
||||
opts.key_fetch.as_ref(),
|
||||
halt.as_ref(),
|
||||
)?))
|
||||
} else {
|
||||
None
|
||||
|
||||
@@ -1339,10 +1339,12 @@ impl Disc {
|
||||
// via the map (identical to `Disc::sweep`). CSS keeps the content-gated
|
||||
// self-descramble path. (Multipass patch is `--raw`, so decrypt is a no-op.)
|
||||
let key_map = if opts.decrypt && decrypt_is_aacs {
|
||||
let halt = opts.halt.clone().map(crate::halt::Halt::from_arc);
|
||||
Some(std::sync::Arc::new(self.resolve_content_key_map(
|
||||
reader,
|
||||
&mut keys,
|
||||
opts.key_fetch.as_ref(),
|
||||
halt.as_ref(),
|
||||
)?))
|
||||
} else {
|
||||
None
|
||||
|
||||
Reference in New Issue
Block a user