Skip to main content

native_ipc/
session.rs

1//! Platform-neutral session negotiation facts.
2
3use crate::batch::{ActiveRegionSet, BatchError, ExpectedBatch, TransferBatch};
4use crate::control::{ControlError, ControlFrame};
5use core::cell::Cell;
6use core::marker::PhantomData;
7#[cfg(any(target_os = "macos", target_os = "windows"))]
8use core::sync::atomic::{AtomicBool, Ordering};
9#[cfg(target_os = "linux")]
10use core::sync::atomic::{AtomicI32, Ordering};
11use std::ffi::OsString;
12use std::num::NonZeroU32;
13#[cfg(target_os = "linux")]
14use std::os::fd::{FromRawFd, OwnedFd};
15#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
16use std::path::Path;
17use std::path::PathBuf;
18use std::time::{Duration, Instant};
19
20pub use crate::liveness::{ActiveLeaseFacts, LeaseFactsConsistency};
21
22#[cfg(target_os = "linux")]
23const RECEIVER_BOOTSTRAP_ENV_PREFIX: &[u8] = b"NATIVE_IPC_VNEXT_BOOTSTRAP_FD=";
24#[cfg(target_os = "linux")]
25const RECEIVER_PUBLIC_BOOTSTRAP_ENV_ENTRY: &[u8] = b"NATIVE_IPC_VNEXT_PUBLIC_BOOTSTRAP=1";
26#[cfg(target_os = "linux")]
27const PR_GET_MDWE: libc::c_int = 66;
28#[cfg(target_os = "linux")]
29const PR_MDWE_REFUSE_EXEC_GAIN: libc::c_ulong = 1;
30#[cfg(target_os = "linux")]
31const BOOTSTRAP_ABSENT: i32 = -2;
32#[cfg(target_os = "linux")]
33const BOOTSTRAP_INVALID: i32 = -1;
34#[cfg(target_os = "linux")]
35const BOOTSTRAP_TAKEN: i32 = -3;
36#[cfg(target_os = "linux")]
37static RECEIVER_BOOTSTRAP_FD: AtomicI32 = AtomicI32::new(BOOTSTRAP_ABSENT);
38#[cfg(any(target_os = "macos", target_os = "windows"))]
39static RECEIVER_BOOTSTRAP_TAKEN: AtomicBool = AtomicBool::new(false);
40
41/// Executable-only ELF preinitializer referenced by [`crate::receiver_main!`].
42///
43/// # Safety
44///
45/// This function may be invoked only by the ELF loader through a
46/// `.preinit_array` entry in the initial receiver executable. Its pointers must
47/// be the loader-supplied initial argument and environment vectors. The hook is
48/// a no-op on non-Linux targets solely to keep the helper-only signature
49/// platform-neutral.
50#[doc(hidden)]
51pub unsafe extern "C" fn __receiver_bootstrap_preinit(
52    _argument_count: core::ffi::c_int,
53    _arguments: *mut *mut core::ffi::c_char,
54    environment: *mut *mut core::ffi::c_char,
55) {
56    #[cfg(target_os = "linux")]
57    // SAFETY: the public hook forwards the loader-supplied environment under
58    // the same pre-initializer contract.
59    unsafe {
60        receiver_bootstrap_preinit_linux(environment);
61    }
62    #[cfg(not(target_os = "linux"))]
63    let _ = environment;
64}
65
66#[cfg(target_os = "linux")]
67unsafe fn receiver_bootstrap_preinit_linux(environment: *mut *mut libc::c_char) {
68    // This ELF pre-initializer runs before Rust main and ordinary init-array
69    // constructors. It performs no allocation and publishes only after all
70    // exact child/descriptor facts and immediate CLOEXEC installation pass.
71    let mut entry = environment;
72    let public_bootstrap = loop {
73        if entry.is_null() {
74            return;
75        }
76        // SAFETY: the loader supplies a null-terminated environment vector.
77        let candidate = unsafe { *entry };
78        if candidate.is_null() {
79            return;
80        }
81        let mut matches = true;
82        for (offset, expected) in RECEIVER_PUBLIC_BOOTSTRAP_ENV_ENTRY.iter().enumerate() {
83            // SAFETY: read only the current byte; a NUL ends this C string and
84            // prevents any later offset from being dereferenced.
85            let actual = unsafe { *candidate.add(offset) }.to_ne_bytes()[0];
86            if actual == 0 || actual != *expected {
87                matches = false;
88                break;
89            }
90        }
91        if matches
92            // SAFETY: the exact fixed entry was readable through its last byte.
93            && unsafe { *candidate.add(RECEIVER_PUBLIC_BOOTSTRAP_ENV_ENTRY.len()) } == 0
94        {
95            break candidate;
96        }
97        // SAFETY: advance within the loader-supplied pointer vector.
98        entry = unsafe { entry.add(1) };
99    };
100    // SAFETY: initial-stack environment strings are writable process storage.
101    // Scrubbing the routing marker before normal code prevents descendants from
102    // reinterpreting this process's one-shot startup designation.
103    unsafe { *public_bootstrap = 0 };
104
105    let mut entry = environment;
106    let value = loop {
107        if entry.is_null() {
108            return;
109        }
110        // SAFETY: the loader supplies a null-terminated environment vector.
111        let candidate = unsafe { *entry };
112        if candidate.is_null() {
113            return;
114        }
115        let mut matches = true;
116        for (offset, expected) in RECEIVER_BOOTSTRAP_ENV_PREFIX.iter().enumerate() {
117            // SAFETY: read only the current byte; a NUL ends this C string and
118            // prevents any later offset from being dereferenced.
119            let actual = unsafe { *candidate.add(offset) }.to_ne_bytes()[0];
120            if actual == 0 || actual != *expected {
121                matches = false;
122                break;
123            }
124        }
125        if matches {
126            // SAFETY: the matched fixed prefix lies within this environment entry.
127            let value = unsafe { candidate.add(RECEIVER_BOOTSTRAP_ENV_PREFIX.len()) };
128            // SAFETY: initial-stack environment strings are writable process
129            // storage. Retain the parsed pointer locally but erase the inherited
130            // numeric authority before any normal constructor or application code.
131            unsafe { *candidate = 0 };
132            break value;
133        }
134        // SAFETY: advance within the loader-supplied pointer vector.
135        entry = unsafe { entry.add(1) };
136    };
137    let mut raw = 0_i32;
138    let mut length = 0_usize;
139    loop {
140        if length == 10 {
141            RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
142            return;
143        }
144        // SAFETY: getenv returned a live NUL-terminated process string.
145        let byte = unsafe { *value.add(length) }.to_ne_bytes()[0];
146        if byte == 0 {
147            break;
148        }
149        if !byte.is_ascii_digit() || (length == 0 && byte == b'0') {
150            RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
151            return;
152        }
153        let Some(next) = raw
154            .checked_mul(10)
155            .and_then(|current| current.checked_add(i32::from(byte - b'0')))
156        else {
157            RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
158            return;
159        };
160        raw = next;
161        length += 1;
162    }
163    if length == 0 || raw < 3 {
164        RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
165        return;
166    }
167
168    // SAFETY: these scalar queries and exact getsockopt output have valid
169    // arguments and do not transfer descriptor ownership.
170    let descriptor_flags = unsafe { libc::fcntl(raw, libc::F_GETFD) };
171    let descriptor_status = unsafe { libc::fcntl(raw, libc::F_GETFL) };
172    let mdwe = unsafe { libc::prctl(PR_GET_MDWE, 0, 0, 0, 0) } as libc::c_ulong;
173    let pid = unsafe { libc::getpid() };
174    let sid = unsafe { libc::getsid(0) };
175    let process_group = unsafe { libc::getpgrp() };
176    let mut socket_type = 0_i32;
177    let mut socket_type_len = core::mem::size_of::<i32>() as libc::socklen_t;
178    let socket_result = unsafe {
179        libc::getsockopt(
180            raw,
181            libc::SOL_SOCKET,
182            libc::SO_TYPE,
183            (&mut socket_type as *mut i32).cast(),
184            &mut socket_type_len,
185        )
186    };
187    if descriptor_flags != 0
188        || descriptor_status < 0
189        || descriptor_status & libc::O_NONBLOCK == 0
190        || mdwe != PR_MDWE_REFUSE_EXEC_GAIN
191        || pid <= 0
192        || sid != pid
193        || process_group != pid
194        || socket_result != 0
195        || socket_type_len as usize != core::mem::size_of::<i32>()
196        || socket_type != libc::SOCK_SEQPACKET
197    {
198        // SAFETY: the process environment designated this live numeric slot as
199        // bootstrap authority before any Rust application code ran. Fail closed
200        // by removing it rather than permitting later Command inheritance.
201        let _ = unsafe { libc::close(raw) };
202        RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
203        return;
204    }
205    // SAFETY: this descriptor is the validated inherited endpoint. Installing
206    // CLOEXEC before any application code removes every safe Command delegation
207    // window. On failure, close the exact startup descriptor.
208    if unsafe { libc::fcntl(raw, libc::F_SETFD, libc::FD_CLOEXEC) } != 0 {
209        let _ = unsafe { libc::close(raw) };
210        RECEIVER_BOOTSTRAP_FD.store(BOOTSTRAP_INVALID, Ordering::Release);
211        return;
212    }
213    RECEIVER_BOOTSTRAP_FD.store(raw, Ordering::Release);
214}
215
216/// Hard protocol maximum for one atomic transfer batch.
217pub const HARD_MAX_REGIONS_PER_BATCH: u16 = 16;
218/// Hard maximum for the opaque HELLO application payload.
219pub const HARD_MAX_BOOTSTRAP_PAYLOAD_BYTES: u32 = 16 * 1024 * 1024;
220/// Hard maximum for one opaque application-control payload.
221pub const HARD_MAX_CONTROL_PAYLOAD_BYTES: u32 = 16 * 1024 * 1024;
222/// Hard maximum logical size of one region.
223pub const HARD_MAX_REGION_BYTES: u64 = 1 << 40;
224/// Hard maximum aggregate bytes in one transaction.
225pub const HARD_MAX_BATCH_BYTES: u64 = 1 << 42;
226/// Hard maximum simultaneously charged region mappings.
227pub const HARD_MAX_ACTIVE_REGIONS: u32 = 1 << 20;
228/// Hard maximum simultaneously charged mapping bytes.
229pub const HARD_MAX_ACTIVE_BYTES: u64 = 1 << 44;
230/// Hard maximum transactions in one fresh session.
231pub const HARD_MAX_TRANSACTIONS: u64 = 1 << 48;
232
233/// Coordinator endpoint marker for [`Session`].
234pub struct Coordinator;
235/// Receiver endpoint marker for [`Session`].
236pub struct Receiver;
237/// Authenticated HELLO state awaiting application decisions.
238pub struct Negotiating;
239/// Bilaterally accepted state that may carry bounded application control.
240pub struct Ready;
241
242/// Availability of the public lifecycle/session composition on this target.
243///
244/// This status applies only to the vNext session layer. The published shared-
245/// memory API remains available on every supported target. Consumers may use
246/// [`backend_status`] as a const preflight or handle
247/// [`SessionError::BackendUnavailable`] from a construction attempt.
248#[derive(Clone, Copy, Debug, Eq, PartialEq)]
249pub enum BackendStatus {
250    /// Public spawn and inherited-bootstrap session construction are composed.
251    Available,
252    /// Reserved for a supported target whose lifecycle adapter is not composed.
253    /// Every target the crate currently compiles for reports [`Self::Available`];
254    /// no supported target returns this today.
255    Unavailable,
256}
257
258/// Reports whether the public lifecycle/session composition is available.
259///
260/// Linux, macOS Arm64, and Windows all report [`BackendStatus::Available`]:
261/// public spawn and inherited-bootstrap session construction are composed on
262/// every supported target. [`BackendStatus::Unavailable`] remains reserved for
263/// targets whose adapter is not composed.
264pub const fn backend_status() -> BackendStatus {
265    BackendStatus::Available
266}
267
268/// Accepted wire protocol version bound into both challenged ACCEPT frames.
269#[derive(Clone, Copy, Debug, Eq, PartialEq)]
270pub struct ProtocolVersion {
271    major: u16,
272    minor: u16,
273}
274
275impl ProtocolVersion {
276    #[allow(dead_code, reason = "wired into accepted session facts below")]
277    pub(crate) const fn new(major: u16, minor: u16) -> Self {
278        Self { major, minor }
279    }
280
281    /// Incompatible-major protocol number.
282    pub const fn major(self) -> u16 {
283        self.major
284    }
285
286    /// Backward-compatible minor protocol number.
287    pub const fn minor(self) -> u16 {
288        self.minor
289    }
290}
291
292/// Locally observed accepted-session reducer state.
293#[derive(Clone, Copy, Debug, Eq, PartialEq)]
294pub enum SessionState {
295    /// Application control and native transactions may be attempted.
296    Ready,
297    /// A terminal ambiguity, malformed peer action, or native failure poisoned the session.
298    Poisoned,
299}
300
301/// Nonblocking peer observation that does not invent an exit code.
302#[derive(Clone, Copy, Debug, Eq, PartialEq)]
303pub enum PeerStatus {
304    /// No authenticated control-endpoint disconnect has been observed.
305    Connected,
306    /// The authenticated control endpoint closed; this does not prove process exit.
307    Disconnected,
308}
309
310/// Exact direct-child termination fact reaped by the coordinator.
311#[derive(Clone, Copy, Debug, Eq, PartialEq)]
312pub enum ChildExitStatus {
313    /// The direct child exited normally with this code.
314    Exited(i32),
315    /// The direct child was terminated by a signal.
316    Signaled {
317        /// Signal number reported by the kernel.
318        signal: i32,
319        /// Whether the kernel reported a core dump.
320        dumped_core: bool,
321    },
322    /// Another process-global waiter consumed the direct-child status first.
323    AlreadyReaped,
324}
325
326/// Bounded statement about descendant cleanup outside the atomic pidfd owner.
327#[derive(Clone, Copy, Debug, Eq, PartialEq)]
328pub enum DescendantCleanupStatus {
329    /// The trusted fresh-session checkpoint was not established.
330    NotEstablished,
331    /// A fresh process group existed, but bounded group termination could not
332    /// be performed under a kernel-witnessed direct-child identity pin.
333    FreshGroupUnverified,
334    /// SIGKILL was delivered to the kernel-verified fresh process group while
335    /// the unreaped direct child pinned its numeric identity, terminating
336    /// every ordinary descendant that had not left the group.
337    FreshGroupTerminated,
338    /// A target-owned containment object proved the complete spawned process tree empty.
339    ContainedProcessTreeComplete,
340    /// A target-owned containment object exists, but bounded cleanup did not prove it empty.
341    OwnedContainmentUnverified,
342}
343
344/// Bounded coordinator-owned direct-child cleanup result.
345#[derive(Clone, Copy, Debug, Eq, PartialEq)]
346pub struct ChildCleanupFacts {
347    direct_child: Option<ChildExitStatus>,
348    descendants: DescendantCleanupStatus,
349    native_error: Option<i32>,
350}
351
352impl ChildCleanupFacts {
353    #[allow(dead_code, reason = "wired into coordinator lifecycle facts below")]
354    pub(crate) const fn new(
355        direct_child: Option<ChildExitStatus>,
356        descendants: DescendantCleanupStatus,
357        native_error: Option<i32>,
358    ) -> Self {
359        Self {
360            direct_child,
361            descendants,
362            native_error,
363        }
364    }
365
366    /// Reaped direct-child status, or `None` when bounded cleanup is incomplete.
367    pub const fn direct_child(self) -> Option<ChildExitStatus> {
368        self.direct_child
369    }
370
371    /// What can safely be claimed about the fresh descendant group.
372    pub const fn descendants(self) -> DescendantCleanupStatus {
373        self.descendants
374    }
375
376    /// Last bounded native errno when cleanup could not complete.
377    pub const fn native_error(self) -> Option<i32> {
378        self.native_error
379    }
380
381    /// Whether the exact direct child has been reaped or was already reaped.
382    pub const fn direct_child_complete(self) -> bool {
383        self.direct_child.is_some()
384    }
385}
386
387/// Recoverable coordinator close result.
388pub enum CoordinatorCloseOutcome {
389    /// No active leases remained and the exact direct child was reaped.
390    Closed(ChildCleanupFacts),
391    /// Active mappings still retain the session; drop them and retry with the returned owner.
392    ActiveLeases {
393        /// Unconsumed live session owner.
394        session: CoordinatorSession<Ready>,
395        /// Bounded current active mapping facts.
396        facts: ActiveLeaseFacts,
397    },
398    /// The deadline elapsed or cleanup failed; the returned owner retains exact child authority.
399    CleanupPending {
400        /// Unconsumed live session owner.
401        session: CoordinatorSession<Ready>,
402        /// Bounded cleanup facts from this attempt.
403        facts: ChildCleanupFacts,
404        /// Exact close failure category and the same retained cleanup evidence.
405        failure: SessionFailure,
406    },
407    /// An unexpected local close transition failed without consuming ownership.
408    Failed {
409        /// Unconsumed session owner that may be aborted or retried.
410        session: CoordinatorSession<Ready>,
411        /// Bounded failure diagnostics including cleanup already attempted.
412        error: SessionFailure,
413    },
414}
415
416/// Recoverable receiver close result.
417pub enum ReceiverCloseOutcome {
418    /// No active mappings remained and the inherited endpoint was closed.
419    Closed,
420    /// Active mappings still retain the session; drop them and retry with the returned owner.
421    ActiveLeases {
422        /// Unconsumed live session owner.
423        session: ReceiverSession<Ready>,
424        /// Bounded current active mapping facts.
425        facts: ActiveLeaseFacts,
426    },
427    /// An unexpected local close transition failed without consuming ownership.
428    Failed {
429        /// Unconsumed session owner that may be aborted or retried.
430        session: ReceiverSession<Ready>,
431        /// Bounded local failure diagnostics.
432        error: SessionFailure,
433    },
434}
435
436/// Terminal coordinator abort result with bounded cleanup diagnostics.
437#[derive(Clone, Copy, Debug, Eq, PartialEq)]
438pub struct CoordinatorAbortOutcome {
439    cleanup: ChildCleanupFacts,
440    failure: Option<SessionFailure>,
441}
442
443impl CoordinatorAbortOutcome {
444    /// Bounded exact-child and descendant cleanup facts.
445    pub const fn cleanup(self) -> ChildCleanupFacts {
446        self.cleanup
447    }
448
449    /// Failure record when bounded termination/reap did not complete.
450    pub const fn failure(self) -> Option<SessionFailure> {
451        self.failure
452    }
453}
454
455/// Role- and state-typed session owner.
456///
457/// The role aliases [`CoordinatorSession`] and [`ReceiverSession`] are the
458/// ordinary spellings. Session values are movable but deliberately not
459/// shareable between threads; every control transition requires `&mut self`.
460pub struct Session<Role, State> {
461    inner: SessionInner,
462    role: PhantomData<Role>,
463    state: PhantomData<State>,
464    not_sync: PhantomData<Cell<()>>,
465}
466
467/// Coordinator-owned exact-child session in the supplied typestate.
468pub type CoordinatorSession<State> = Session<Coordinator, State>;
469/// Receiver-owned inherited-bootstrap session in the supplied typestate.
470pub type ReceiverSession<State> = Session<Receiver, State>;
471
472/// Unique inherited receiver bootstrap authority.
473///
474/// Ordinary helpers obtain this token only from [`crate::receiver_main!`]. Consuming
475/// the token transfers the sole inherited native endpoint into negotiation;
476/// it is non-cloneable and exposes no raw descriptor.
477pub struct ReceiverBootstrap {
478    #[cfg(target_os = "linux")]
479    inherited: OwnedFd,
480    not_sync: PhantomData<Cell<()>>,
481}
482
483/// Defines a helper-process entry point with one ownership-bearing bootstrap.
484///
485/// The supplied closure receives `Result<ReceiverBootstrap, SessionFailure>` and
486/// runs only after the library has attempted the one-shot reservation take.
487/// Linux validates and reserves its inherited descriptor in an ELF
488/// pre-initializer. macOS consumes its one-shot bootstrap designation from
489/// Rust main and scrubs the public marker there; the Mach nonce and parent
490/// identity are taken and scrubbed when the receiver session connects.
491/// Windows takes and scrubs its pipe, nonce, and parent designation when the
492/// receiver session connects from the environment.
493#[macro_export]
494macro_rules! receiver_main {
495    ($entry:expr) => {
496        #[cfg(target_os = "linux")]
497        #[used]
498        #[unsafe(link_section = ".preinit_array")]
499        static NATIVE_IPC_RECEIVER_BOOTSTRAP_PREINIT: unsafe extern "C" fn(
500            ::core::ffi::c_int,
501            *mut *mut ::core::ffi::c_char,
502            *mut *mut ::core::ffi::c_char,
503        ) = $crate::session::__receiver_bootstrap_preinit;
504
505        fn main() {
506            let bootstrap = $crate::session::__take_receiver_bootstrap();
507            ($entry)(bootstrap);
508        }
509    };
510}
511
512/// Takes the pre-initialized inherited endpoint exactly once.
513///
514/// This is exported only so [`crate::receiver_main!`] can expand in downstream
515/// crates. Applications must invoke that macro instead of calling this hook.
516#[doc(hidden)]
517pub fn __take_receiver_bootstrap() -> Result<ReceiverBootstrap, SessionFailure> {
518    #[cfg(target_os = "linux")]
519    {
520        let raw = RECEIVER_BOOTSTRAP_FD.swap(BOOTSTRAP_TAKEN, Ordering::AcqRel);
521        if raw < 3 {
522            return Err(SessionFailure::new(
523                SessionOperation::Bootstrap,
524                SessionTransactionState::NotEstablished,
525                SessionError::InvalidInput,
526            ));
527        }
528        // SAFETY: the pre-initializer reserved this validated descriptor for
529        // the one successful atomic take and installed CLOEXEC before main.
530        let inherited = unsafe { OwnedFd::from_raw_fd(raw) };
531        Ok(ReceiverBootstrap {
532            inherited,
533            not_sync: PhantomData,
534        })
535    }
536    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
537    {
538        Err(SessionFailure::new(
539            SessionOperation::Bootstrap,
540            SessionTransactionState::NotEstablished,
541            SessionError::BackendUnavailable,
542        ))
543    }
544    #[cfg(target_os = "windows")]
545    {
546        if RECEIVER_BOOTSTRAP_TAKEN.swap(true, Ordering::AcqRel)
547            || std::env::var_os("NATIVE_IPC_VNEXT_PUBLIC_BOOTSTRAP").as_deref()
548                != Some(std::ffi::OsStr::new("1"))
549        {
550            return Err(SessionFailure::new(
551                SessionOperation::Bootstrap,
552                SessionTransactionState::NotEstablished,
553                SessionError::InvalidInput,
554            ));
555        }
556        Ok(ReceiverBootstrap {
557            not_sync: PhantomData,
558        })
559    }
560    #[cfg(target_os = "macos")]
561    {
562        if RECEIVER_BOOTSTRAP_TAKEN.swap(true, Ordering::AcqRel)
563            || std::env::var_os("NATIVE_IPC_VNEXT_PUBLIC_BOOTSTRAP").as_deref()
564                != Some(std::ffi::OsStr::new("1"))
565        {
566            return Err(SessionFailure::new(
567                SessionOperation::Bootstrap,
568                SessionTransactionState::NotEstablished,
569                SessionError::InvalidInput,
570            ));
571        }
572        // Scrub the one-shot routing marker so descendants of this receiver
573        // cannot reinterpret its bootstrap designation, matching the Linux
574        // pre-init and Windows connect scrubs. The Mach nonce and parent PID are
575        // scrubbed where they are consumed, in `ChildChannel::connect_from_environment`.
576        // SAFETY: the bootstrap environment is process-local startup state
577        // consumed exactly once here before any application or descendant code.
578        unsafe { std::env::remove_var("NATIVE_IPC_VNEXT_PUBLIC_BOOTSTRAP") };
579        Ok(ReceiverBootstrap {
580            not_sync: PhantomData,
581        })
582    }
583}
584
585enum SessionInner {
586    #[cfg(target_os = "linux")]
587    CoordinatorNegotiating(crate::backend::linux_vnext::spawn::LinuxCoordinatorNegotiatingSession),
588    #[cfg(target_os = "linux")]
589    ReceiverNegotiating(crate::backend::linux_vnext::spawn::LinuxReceiverNegotiatingSession),
590    #[cfg(target_os = "linux")]
591    CoordinatorReady(crate::backend::linux_vnext::spawn::LinuxCoordinatorReadySession),
592    #[cfg(target_os = "linux")]
593    ReceiverReady(crate::backend::linux_vnext::spawn::LinuxReceiverReadySession),
594    #[cfg(target_os = "macos")]
595    CoordinatorNegotiating(crate::backend::macos::vnext_session::MacCoordinatorNegotiatingSession),
596    #[cfg(target_os = "macos")]
597    ReceiverNegotiating(crate::backend::macos::vnext_session::MacReceiverNegotiatingSession),
598    #[cfg(target_os = "macos")]
599    CoordinatorReady(crate::backend::macos::vnext_session::MacCoordinatorReadySession),
600    #[cfg(target_os = "macos")]
601    ReceiverReady(crate::backend::macos::vnext_session::MacReceiverReadySession),
602    #[cfg(target_os = "windows")]
603    CoordinatorNegotiating(
604        Box<crate::backend::windows::vnext_session::WindowsCoordinatorNegotiatingSession>,
605    ),
606    #[cfg(target_os = "windows")]
607    ReceiverNegotiating(
608        Box<crate::backend::windows::vnext_session::WindowsReceiverNegotiatingSession>,
609    ),
610    #[cfg(target_os = "windows")]
611    CoordinatorReady(Box<crate::backend::windows::vnext_session::WindowsCoordinatorReadySession>),
612    #[cfg(target_os = "windows")]
613    ReceiverReady(Box<crate::backend::windows::vnext_session::WindowsReceiverReadySession>),
614    #[allow(dead_code)]
615    Unavailable,
616}
617
618/// Required executable-identity policy for an owned helper launch.
619#[derive(Clone, Copy, Debug, Eq, PartialEq)]
620pub enum ExecutableIdentityPolicy {
621    /// Open and retain one absolute regular executable without any symlink
622    /// traversal and apply the target's documented image-identity checks.
623    /// Linux executes the held object directly. macOS authenticates the
624    /// running image against the retained file by content: the kernel-
625    /// registered code-directory hash of the exact audit-token-bound child
626    /// execution must match a hash computed from the held descriptor, at
627    /// launch and again through ACCEPT, independent of pathnames and of the
628    /// signing identity (an ad-hoc linker signature suffices). A macOS
629    /// executable that carries no code directory — an unsigned image or a
630    /// script — cannot be bound and fails construction closed. Windows
631    /// retains the opened file, spawns from the retained image, binds the
632    /// session transport to the exact spawned process identity, and holds
633    /// the child and its descendants in a kill-on-close Job.
634    ExactOpenedFile,
635}
636
637/// Exact child command. The environment is explicit and starts empty.
638#[derive(Clone, Debug, Eq, PartialEq)]
639pub struct SessionCommand {
640    executable: PathBuf,
641    arguments: Vec<OsString>,
642    environment: Vec<(OsString, OsString)>,
643}
644
645impl SessionCommand {
646    /// Starts a command whose argument zero is the supplied executable path.
647    pub fn new(executable: impl Into<PathBuf>) -> Self {
648        let executable = executable.into();
649        Self {
650            arguments: vec![executable.as_os_str().to_owned()],
651            executable,
652            environment: Vec::new(),
653        }
654    }
655
656    /// Replaces argument zero without changing the selected executable path.
657    pub fn arg0(mut self, argument: impl Into<OsString>) -> Self {
658        self.arguments[0] = argument.into();
659        self
660    }
661
662    /// Appends one exact child argument.
663    pub fn arg(mut self, argument: impl Into<OsString>) -> Self {
664        self.arguments.push(argument.into());
665        self
666    }
667
668    /// Adds or replaces one exact child environment entry.
669    pub fn env(mut self, key: impl Into<OsString>, value: impl Into<OsString>) -> Self {
670        let key = key.into();
671        let value = value.into();
672        if let Some((_, existing)) = self
673            .environment
674            .iter_mut()
675            .find(|(existing, _)| *existing == key)
676        {
677            *existing = value;
678        } else {
679            self.environment.push((key, value));
680        }
681        self
682    }
683
684    /// The cross-platform union of reserved bootstrap environment names.
685    /// Every target rejects the full union so a command that spawns on one
686    /// platform is not silently accepted with a reserved key on another.
687    fn has_reserved_environment(&self) -> bool {
688        const RESERVED: [&str; 6] = [
689            "NATIVE_IPC_VNEXT_BOOTSTRAP_FD",
690            "NATIVE_IPC_VNEXT_PUBLIC_BOOTSTRAP",
691            "NATIVE_IPC_MACH_NONCE",
692            "NATIVE_IPC_PARENT_PID",
693            "NATIVE_IPC_WINDOWS_PIPE",
694            "NATIVE_IPC_WINDOWS_NONCE",
695        ];
696        self.environment.iter().any(|(key, _)| {
697            RESERVED
698                .iter()
699                .any(|name| key.as_os_str() == std::ffi::OsStr::new(name))
700        })
701    }
702
703    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
704    pub(crate) fn executable(&self) -> &Path {
705        &self.executable
706    }
707
708    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
709    pub(crate) fn arguments(&self) -> &[OsString] {
710        &self.arguments
711    }
712
713    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
714    pub(crate) fn environment(&self) -> &[(OsString, OsString)] {
715        &self.environment
716    }
717}
718
719/// Finite negotiation inputs retained under one caller-derived deadline.
720#[derive(Clone, Debug, Eq, PartialEq)]
721pub struct SessionOptions {
722    deadline: AbsoluteDeadline,
723    limits: SessionLimits,
724    application_payload: Vec<u8>,
725    executable_identity: ExecutableIdentityPolicy,
726    require_atomic_u32: bool,
727    require_atomic_u64: bool,
728}
729
730impl SessionOptions {
731    /// Creates an exact-deadline offer with finite default limits.
732    pub fn new(deadline: AbsoluteDeadline, executable_identity: ExecutableIdentityPolicy) -> Self {
733        Self {
734            deadline,
735            limits: SessionLimits::default(),
736            application_payload: Vec::new(),
737            executable_identity,
738            require_atomic_u32: false,
739            require_atomic_u64: false,
740        }
741    }
742
743    /// Replaces the finite local limit offer.
744    pub fn with_limits(mut self, limits: SessionLimits) -> Self {
745        self.limits = limits;
746        self
747    }
748
749    /// Replaces the bounded opaque application HELLO payload.
750    pub fn with_application_payload(mut self, payload: Vec<u8>) -> Self {
751        self.application_payload = payload;
752        self
753    }
754
755    /// Requires lock-free cross-process 32-bit atomic support.
756    pub fn require_atomic_u32(mut self) -> Self {
757        self.require_atomic_u32 = true;
758        self
759    }
760
761    /// Requires lock-free cross-process 64-bit atomic support.
762    pub fn require_atomic_u64(mut self) -> Self {
763        self.require_atomic_u64 = true;
764        self
765    }
766
767    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
768    pub(crate) const fn limits(&self) -> SessionLimits {
769        self.limits
770    }
771
772    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
773    pub(crate) fn application_payload(&self) -> &[u8] {
774        &self.application_payload
775    }
776
777    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
778    pub(crate) const fn requires_atomic_u32(&self) -> bool {
779        self.require_atomic_u32
780    }
781
782    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
783    pub(crate) const fn requires_atomic_u64(&self) -> bool {
784        self.require_atomic_u64
785    }
786
787    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
788    pub(crate) const fn deadline(&self) -> AbsoluteDeadline {
789        self.deadline
790    }
791}
792
793/// Endpoint that made a clean application negotiation rejection.
794#[derive(Clone, Copy, Debug, Eq, PartialEq)]
795pub enum SessionEndpoint {
796    /// Spawning owner of the exact helper.
797    Coordinator,
798    /// Exact inherited-bootstrap helper.
799    Receiver,
800}
801
802/// Nonzero application negotiation rejection reason.
803#[derive(Clone, Copy, Debug, Eq, PartialEq)]
804pub struct RejectionReason(NonZeroU32);
805
806impl RejectionReason {
807    /// The application declined without a more specific incompatibility.
808    pub const APPLICATION_DECLINED: Self = Self(NonZeroU32::MIN);
809    /// Application protocols or schemas are incompatible.
810    pub const INCOMPATIBLE_APPLICATION_PROTOCOL: Self =
811        Self(NonZeroU32::new(2).expect("two is nonzero"));
812    /// Local application policy rejected the peer.
813    pub const APPLICATION_POLICY: Self = Self(NonZeroU32::new(3).expect("three is nonzero"));
814
815    /// Constructs an application-specific reason from the high-half namespace.
816    pub const fn application_specific(value: u32) -> Option<Self> {
817        if value < 0x8000_0000 {
818            return None;
819        }
820        match NonZeroU32::new(value) {
821            Some(value) => Some(Self(value)),
822            None => None,
823        }
824    }
825
826    /// Numeric wire value for logging or application dispatch.
827    pub const fn get(self) -> u32 {
828        self.0.get()
829    }
830
831    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
832    fn from_wire(value: NonZeroU32) -> Option<Self> {
833        match value.get() {
834            1 => Some(Self::APPLICATION_DECLINED),
835            2 => Some(Self::INCOMPATIBLE_APPLICATION_PROTOCOL),
836            3 => Some(Self::APPLICATION_POLICY),
837            value => Self::application_specific(value),
838        }
839    }
840
841    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
842    const fn as_nonzero(self) -> NonZeroU32 {
843        self.0
844    }
845}
846
847/// Explicit application decision after the peer HELLO is available.
848#[derive(Clone, Copy, Debug, Eq, PartialEq)]
849pub enum NegotiationDecision {
850    /// Accept the peer's bounded opaque HELLO payload and negotiated facts.
851    Accept,
852    /// Cleanly reject with a fixed nonzero application reason.
853    Reject(RejectionReason),
854}
855
856/// Clean application-level result of the challenged negotiation.
857pub enum NegotiationOutcome<T> {
858    /// Bilateral exact ACCEPT yielded the ready session owner.
859    Accepted(T),
860    /// One endpoint made a canonical clean application rejection.
861    Rejected {
862        /// Endpoint that rejected.
863        by: SessionEndpoint,
864        /// Exact nonzero reason carried by the peer or local decision.
865        reason: RejectionReason,
866        /// Coordinator-owned child cleanup facts; receivers have no child authority.
867        cleanup: Option<ChildCleanupFacts>,
868    },
869}
870
871/// Public session construction, negotiation, or control failure.
872#[derive(Clone, Copy, Debug, Eq, PartialEq)]
873pub enum SessionError {
874    /// The selected native target adapter is not composed yet.
875    BackendUnavailable,
876    /// Local command, environment, payload, or option input is invalid.
877    InvalidInput,
878    /// The one caller-derived absolute deadline expired.
879    DeadlineExpired,
880    /// The authenticated control endpoint closed before the operation completed.
881    PeerDisconnected,
882    /// Kernel-authenticated process or executable identity did not match.
883    IdentityMismatch,
884    /// The peer supplied malformed or noncanonical framing.
885    MalformedPeer,
886    /// Local I/O completed at the deadline boundary with unknowable peer state.
887    Ambiguous,
888    /// HELLO or challenged decision validation failed.
889    NegotiationFailed,
890    /// Local native capability discovery or limit negotiation failed.
891    NativeNegotiation(NegotiationError),
892    /// Application-control sequencing or bounds validation failed.
893    Control(ControlError),
894    /// Portable batch construction or committed-set validation failed.
895    Batch(BatchError),
896    /// Current active region or byte capacity cannot admit the whole batch.
897    ActiveLimit,
898    /// The peer reported a bounded local native-preparation failure before capability transfer.
899    PeerPreparationFailed,
900    /// Native mapping activation failed atomically without exposing a partial set.
901    ActivationFailed,
902    /// Native negotiation transport was already terminally poisoned.
903    Poisoned,
904    /// A bounded native operation failed without a more specific safe category.
905    Native,
906}
907
908impl core::fmt::Display for SessionError {
909    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
910        write!(formatter, "session operation failed: {self:?}")
911    }
912}
913
914impl std::error::Error for SessionError {}
915
916/// Bounded public operation category attached to a session failure.
917#[derive(Clone, Copy, Debug, Eq, PartialEq)]
918pub enum SessionOperation {
919    /// Process-entry bootstrap adoption.
920    Bootstrap,
921    /// Exact child spawn and authenticated HELLO exchange.
922    Spawn,
923    /// Bilateral application negotiation.
924    Negotiate,
925    /// Nonblocking peer observation.
926    PollPeer,
927    /// Bounded peer/direct-child wait.
928    WaitForExit,
929    /// Graceful session close.
930    Close,
931    /// Terminal session abort.
932    Abort,
933    /// Coordinator capability transfer and activation.
934    TransferBatch,
935    /// Receiver capability import and activation.
936    ReceiveBatch,
937    /// Opaque application-control send.
938    SendControl,
939    /// Opaque application-control receive.
940    ReceiveControl,
941}
942
943/// Bounded reducer state observed for a failed public operation.
944#[derive(Clone, Copy, Debug, Eq, PartialEq)]
945pub enum SessionTransactionState {
946    /// No session owner had been established.
947    NotEstablished,
948    /// An exact child exists, but authenticated HELLO negotiation has not begun.
949    Spawned,
950    /// The authenticated endpoints were still negotiating.
951    Negotiating,
952    /// The accepted control reducer was idle and ready.
953    Ready,
954    /// A native capability transaction had begun. Only backends whose batch
955    /// activation is non-atomic report this state (Linux); macOS and Windows
956    /// activate atomically and expose no partially-open transaction, so a
957    /// portable consumer must not depend on observing it on every target.
958    TransactionOpen,
959    /// The session reducer was terminally poisoned.
960    Poisoned,
961}
962
963/// Bounded diagnostics retained for a failed public session operation.
964#[derive(Clone, Copy, Debug, Eq, PartialEq)]
965pub struct SessionFailure {
966    operation: SessionOperation,
967    transaction_state: SessionTransactionState,
968    reason: SessionError,
969    native_code: Option<i32>,
970    poisoned: bool,
971    peer: Option<PeerStatus>,
972    cleanup: Option<ChildCleanupFacts>,
973}
974
975impl SessionFailure {
976    const fn new(
977        operation: SessionOperation,
978        transaction_state: SessionTransactionState,
979        reason: SessionError,
980    ) -> Self {
981        Self {
982            operation,
983            transaction_state,
984            reason,
985            native_code: None,
986            poisoned: matches!(transaction_state, SessionTransactionState::Poisoned),
987            peer: if matches!(reason, SessionError::PeerDisconnected) {
988                Some(PeerStatus::Disconnected)
989            } else {
990                None
991            },
992            cleanup: None,
993        }
994    }
995
996    const fn with_cleanup(mut self, cleanup: ChildCleanupFacts) -> Self {
997        self.cleanup = Some(cleanup);
998        self
999    }
1000
1001    #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1002    const fn with_optional_cleanup(mut self, cleanup: Option<ChildCleanupFacts>) -> Self {
1003        self.cleanup = cleanup;
1004        self
1005    }
1006
1007    const fn with_native_code(mut self, native_code: Option<i32>) -> Self {
1008        self.native_code = native_code;
1009        self
1010    }
1011
1012    const fn with_poisoned(mut self, poisoned: bool) -> Self {
1013        self.poisoned = poisoned;
1014        self
1015    }
1016
1017    /// Public operation that failed.
1018    pub const fn operation(self) -> SessionOperation {
1019        self.operation
1020    }
1021
1022    /// Reducer/transaction state observed for the failure.
1023    pub const fn transaction_state(self) -> SessionTransactionState {
1024        self.transaction_state
1025    }
1026
1027    /// Portable bounded failure reason.
1028    pub const fn reason(self) -> SessionError {
1029        self.reason
1030    }
1031
1032    /// Native error code when the backend can preserve one safely.
1033    pub const fn native_code(self) -> Option<i32> {
1034        self.native_code
1035    }
1036
1037    /// Whether the operation left the session terminally poisoned.
1038    pub const fn is_poisoned(self) -> bool {
1039        self.poisoned
1040    }
1041
1042    /// Bounded peer observation associated with the failure.
1043    pub const fn peer(self) -> Option<PeerStatus> {
1044        self.peer
1045    }
1046
1047    /// Coordinator-owned cleanup facts, when this operation consumed child authority.
1048    pub const fn cleanup(self) -> Option<ChildCleanupFacts> {
1049        self.cleanup
1050    }
1051}
1052
1053impl core::fmt::Display for SessionFailure {
1054    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1055        write!(
1056            formatter,
1057            "session {:?} failed in {:?}: {:?}",
1058            self.operation, self.transaction_state, self.reason
1059        )
1060    }
1061}
1062
1063impl std::error::Error for SessionFailure {}
1064
1065/// Finite resource limits offered and negotiated by both endpoints.
1066#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1067pub struct SessionLimits {
1068    /// Maximum entries in one batch; hard maximum sixteen.
1069    pub max_regions_per_batch: u16,
1070    /// Maximum logical bytes in one region.
1071    pub max_region_bytes: u64,
1072    /// Maximum aggregate logical/mapped bytes in one batch.
1073    pub max_batch_bytes: u64,
1074    /// Maximum charged active region mappings.
1075    pub max_active_regions: u32,
1076    /// Maximum charged active mapping bytes.
1077    pub max_active_bytes: u64,
1078    /// Maximum monotonically increasing transactions.
1079    pub max_transactions: u64,
1080    /// Maximum opaque HELLO application payload bytes.
1081    pub max_bootstrap_payload_bytes: u32,
1082    /// Maximum opaque application-control payload bytes.
1083    pub max_control_payload_bytes: u32,
1084}
1085
1086impl Default for SessionLimits {
1087    fn default() -> Self {
1088        Self {
1089            max_regions_per_batch: 16,
1090            max_region_bytes: 256 * 1024 * 1024,
1091            max_batch_bytes: 1024 * 1024 * 1024,
1092            max_active_regions: 4096,
1093            max_active_bytes: 8 * 1024 * 1024 * 1024,
1094            max_transactions: 1 << 32,
1095            max_bootstrap_payload_bytes: 1024 * 1024,
1096            max_control_payload_bytes: 1024 * 1024,
1097        }
1098    }
1099}
1100
1101/// Invalid local or peer negotiation offer.
1102#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1103pub enum NegotiationError {
1104    /// A numeric limit is zero.
1105    ZeroLimit,
1106    /// A numeric limit exceeds its field-specific hard maximum.
1107    AboveHardMaximum,
1108    /// A byte limit cannot narrow to this target's `usize`.
1109    NativeSizeNarrowing,
1110    /// Required lock-free atomic width is not available.
1111    AtomicUnsupported,
1112    /// A monotonic deadline cannot be represented.
1113    InvalidDeadline,
1114}
1115
1116impl core::fmt::Display for NegotiationError {
1117    fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1118        write!(formatter, "session negotiation failed: {self:?}")
1119    }
1120}
1121
1122impl std::error::Error for NegotiationError {}
1123
1124impl SessionLimits {
1125    /// Validates every field before allocation or native import.
1126    pub fn validate(self) -> Result<Self, NegotiationError> {
1127        self.validate_for_native_max(usize::MAX as u64)
1128    }
1129
1130    fn validate_for_native_max(self, native_usize_max: u64) -> Result<Self, NegotiationError> {
1131        if self.max_regions_per_batch == 0
1132            || self.max_region_bytes == 0
1133            || self.max_batch_bytes == 0
1134            || self.max_active_regions == 0
1135            || self.max_active_bytes == 0
1136            || self.max_transactions == 0
1137            || self.max_bootstrap_payload_bytes == 0
1138            || self.max_control_payload_bytes == 0
1139        {
1140            return Err(NegotiationError::ZeroLimit);
1141        }
1142        if self.max_regions_per_batch > HARD_MAX_REGIONS_PER_BATCH
1143            || self.max_region_bytes > HARD_MAX_REGION_BYTES
1144            || self.max_batch_bytes > HARD_MAX_BATCH_BYTES
1145            || self.max_active_regions > HARD_MAX_ACTIVE_REGIONS
1146            || self.max_active_bytes > HARD_MAX_ACTIVE_BYTES
1147            || self.max_transactions > HARD_MAX_TRANSACTIONS
1148            || self.max_bootstrap_payload_bytes > HARD_MAX_BOOTSTRAP_PAYLOAD_BYTES
1149            || self.max_control_payload_bytes > HARD_MAX_CONTROL_PAYLOAD_BYTES
1150        {
1151            return Err(NegotiationError::AboveHardMaximum);
1152        }
1153        if self.max_region_bytes > native_usize_max
1154            || self.max_batch_bytes > native_usize_max
1155            || self.max_active_bytes > native_usize_max
1156            || u64::from(self.max_bootstrap_payload_bytes) > native_usize_max
1157            || u64::from(self.max_control_payload_bytes) > native_usize_max
1158        {
1159            return Err(NegotiationError::NativeSizeNarrowing);
1160        }
1161        Ok(self)
1162    }
1163
1164    /// Computes checked effective minima after validating both offers.
1165    pub fn negotiate(local: Self, peer: Self) -> Result<Self, NegotiationError> {
1166        let local = local.validate()?;
1167        let peer = peer.validate()?;
1168        Self {
1169            max_regions_per_batch: local.max_regions_per_batch.min(peer.max_regions_per_batch),
1170            max_region_bytes: local.max_region_bytes.min(peer.max_region_bytes),
1171            max_batch_bytes: local.max_batch_bytes.min(peer.max_batch_bytes),
1172            max_active_regions: local.max_active_regions.min(peer.max_active_regions),
1173            max_active_bytes: local.max_active_bytes.min(peer.max_active_bytes),
1174            max_transactions: local.max_transactions.min(peer.max_transactions),
1175            max_bootstrap_payload_bytes: local
1176                .max_bootstrap_payload_bytes
1177                .min(peer.max_bootstrap_payload_bytes),
1178            max_control_payload_bytes: local
1179                .max_control_payload_bytes
1180                .min(peer.max_control_payload_bytes),
1181        }
1182        .validate()
1183    }
1184}
1185
1186/// Cross-process atomic and layout alignment facts for the selected target.
1187#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1188pub struct AtomicCapabilities {
1189    atomic_u32_lock_free: bool,
1190    atomic_u32_alignment: usize,
1191    atomic_u64_lock_free: bool,
1192    atomic_u64_alignment: usize,
1193    page_alignment: usize,
1194    cache_line_alignment: usize,
1195}
1196
1197impl AtomicCapabilities {
1198    pub(crate) const fn from_accepted_offer(value: crate::negotiation::AtomicOffer) -> Self {
1199        Self {
1200            atomic_u32_lock_free: value.u32_lock_free,
1201            atomic_u32_alignment: value.u32_alignment as usize,
1202            atomic_u64_lock_free: value.u64_lock_free,
1203            atomic_u64_alignment: value.u64_alignment as usize,
1204            page_alignment: value.page_alignment as usize,
1205            cache_line_alignment: value.cache_line_alignment as usize,
1206        }
1207    }
1208
1209    /// Constructs facts only after private native discovery has established
1210    /// lock freedom and runtime page/cache-line alignment.
1211    #[allow(dead_code, reason = "wired into native HELLO discovery in phase 4b")]
1212    pub(crate) fn from_verified_native(
1213        page_alignment: usize,
1214        cache_line_alignment: usize,
1215        atomic_u32_lock_free: bool,
1216        atomic_u64_lock_free: bool,
1217    ) -> Result<Self, NegotiationError> {
1218        let atomic_u32_alignment = core::mem::align_of::<core::sync::atomic::AtomicU32>();
1219        let atomic_u64_alignment = core::mem::align_of::<core::sync::atomic::AtomicU64>();
1220        if !page_alignment.is_power_of_two()
1221            || !cache_line_alignment.is_power_of_two()
1222            || page_alignment < atomic_u32_alignment.max(atomic_u64_alignment)
1223            || cache_line_alignment < atomic_u32_alignment.max(atomic_u64_alignment)
1224        {
1225            return Err(NegotiationError::AtomicUnsupported);
1226        }
1227        Ok(Self {
1228            atomic_u32_lock_free,
1229            atomic_u32_alignment,
1230            atomic_u64_lock_free,
1231            atomic_u64_alignment,
1232            page_alignment,
1233            cache_line_alignment,
1234        })
1235    }
1236
1237    /// Whether private target discovery established lock-free 32-bit atomics.
1238    pub fn atomic_u32_lock_free(self) -> bool {
1239        self.atomic_u32_lock_free
1240    }
1241
1242    /// Required alignment for an atomic 32-bit value.
1243    pub fn atomic_u32_alignment(self) -> usize {
1244        self.atomic_u32_alignment
1245    }
1246
1247    /// Whether private target discovery established lock-free 64-bit atomics.
1248    pub fn atomic_u64_lock_free(self) -> bool {
1249        self.atomic_u64_lock_free
1250    }
1251
1252    /// Required alignment for an atomic 64-bit value.
1253    pub fn atomic_u64_alignment(self) -> usize {
1254        self.atomic_u64_alignment
1255    }
1256
1257    /// Runtime native page alignment.
1258    pub fn page_alignment(self) -> usize {
1259        self.page_alignment
1260    }
1261
1262    /// Runtime native cache-line alignment used by application layouts.
1263    pub fn cache_line_alignment(self) -> usize {
1264        self.cache_line_alignment
1265    }
1266
1267    /// Rejects negotiation if required widths are unavailable.
1268    #[allow(dead_code, reason = "wired into native HELLO negotiation in phase 4b")]
1269    pub(crate) fn require(
1270        self,
1271        u32_required: bool,
1272        u64_required: bool,
1273    ) -> Result<Self, NegotiationError> {
1274        if (u32_required && !self.atomic_u32_lock_free)
1275            || (u64_required && !self.atomic_u64_lock_free)
1276        {
1277            return Err(NegotiationError::AtomicUnsupported);
1278        }
1279        Ok(self)
1280    }
1281}
1282
1283/// One monotonic absolute deadline shared by a complete operation.
1284#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1285pub struct AbsoluteDeadline(Instant);
1286
1287impl AbsoluteDeadline {
1288    /// Derives a deadline once at operation entry.
1289    pub fn after(duration: Duration) -> Result<Self, NegotiationError> {
1290        if duration.is_zero() {
1291            return Err(NegotiationError::InvalidDeadline);
1292        }
1293        Instant::now()
1294            .checked_add(duration)
1295            .map(Self)
1296            .ok_or(NegotiationError::InvalidDeadline)
1297    }
1298
1299    /// Returns the remaining duration, or zero after expiry.
1300    pub fn remaining(self) -> Duration {
1301        self.0.saturating_duration_since(Instant::now())
1302    }
1303
1304    /// Whether the absolute deadline has expired.
1305    pub fn is_expired(self) -> bool {
1306        self.remaining().is_zero()
1307    }
1308}
1309
1310#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1311impl<Role, State> Session<Role, State> {
1312    fn from_inner(inner: SessionInner) -> Self {
1313        Self {
1314            inner,
1315            role: PhantomData,
1316            state: PhantomData,
1317            not_sync: PhantomData,
1318        }
1319    }
1320}
1321
1322impl Session<Coordinator, Negotiating> {
1323    /// Spawns and authenticates the selected helper under the target's
1324    /// documented executable-identity policy through both HELLOs.
1325    pub fn spawn(command: SessionCommand, options: SessionOptions) -> Result<Self, SessionFailure> {
1326        validate_public_options(&options).map_err(|reason| {
1327            SessionFailure::new(
1328                SessionOperation::Spawn,
1329                SessionTransactionState::NotEstablished,
1330                reason,
1331            )
1332        })?;
1333        if command.has_reserved_environment() {
1334            return Err(SessionFailure::new(
1335                SessionOperation::Spawn,
1336                SessionTransactionState::NotEstablished,
1337                SessionError::InvalidInput,
1338            ));
1339        }
1340        #[cfg(target_os = "linux")]
1341        {
1342            let inner =
1343                crate::backend::linux_vnext::spawn::LinuxCoordinatorNegotiatingSession::spawn(
1344                    &command, &options,
1345                )
1346                .map_err(|failure| {
1347                    let native_code = linux_public_native_code(failure.error);
1348                    let transaction_state = match failure.state {
1349                        crate::backend::linux_vnext::spawn::LinuxCoordinatorFailureState::NotEstablished => {
1350                            SessionTransactionState::NotEstablished
1351                        }
1352                        crate::backend::linux_vnext::spawn::LinuxCoordinatorFailureState::Spawned => {
1353                            SessionTransactionState::Spawned
1354                        }
1355                        crate::backend::linux_vnext::spawn::LinuxCoordinatorFailureState::Negotiating => {
1356                            SessionTransactionState::Negotiating
1357                        }
1358                    };
1359                    SessionFailure::new(
1360                        SessionOperation::Spawn,
1361                        transaction_state,
1362                        failure.error.into(),
1363                    )
1364                    .with_native_code(native_code)
1365                    .with_poisoned(failure.poisoned)
1366                    .with_optional_cleanup(failure.cleanup)
1367                })?;
1368            Ok(Self::from_inner(SessionInner::CoordinatorNegotiating(
1369                inner,
1370            )))
1371        }
1372        #[cfg(target_os = "macos")]
1373        {
1374            let inner =
1375                crate::backend::macos::vnext_session::MacCoordinatorNegotiatingSession::spawn(
1376                    &command, &options,
1377                )
1378                .map_err(|failure| {
1379                    let transaction_state = match failure.state {
1380                        crate::backend::macos::vnext_session::MacCoordinatorFailureState::NotEstablished => {
1381                            SessionTransactionState::NotEstablished
1382                        }
1383                        crate::backend::macos::vnext_session::MacCoordinatorFailureState::Spawned => {
1384                            SessionTransactionState::Spawned
1385                        }
1386                        crate::backend::macos::vnext_session::MacCoordinatorFailureState::Negotiating => {
1387                            SessionTransactionState::Negotiating
1388                        }
1389                    };
1390                    mac_session_failure(
1391                        SessionOperation::Spawn,
1392                        transaction_state,
1393                        failure.error,
1394                        failure.poisoned,
1395                    )
1396                    .with_optional_cleanup(failure.cleanup)
1397                })?;
1398            Ok(Self::from_inner(SessionInner::CoordinatorNegotiating(
1399                inner,
1400            )))
1401        }
1402        #[cfg(target_os = "windows")]
1403        {
1404            let inner = crate::backend::windows::vnext_session::WindowsCoordinatorNegotiatingSession::spawn(
1405                &command,
1406                &options,
1407            )
1408            .map_err(|failure| {
1409                let transaction_state = match failure.state {
1410                    crate::backend::windows::vnext_session::WindowsCoordinatorFailureState::NotEstablished => SessionTransactionState::NotEstablished,
1411                    crate::backend::windows::vnext_session::WindowsCoordinatorFailureState::Spawned => SessionTransactionState::Spawned,
1412                    crate::backend::windows::vnext_session::WindowsCoordinatorFailureState::Negotiating => SessionTransactionState::Negotiating,
1413                };
1414                windows_session_failure(
1415                    SessionOperation::Spawn,
1416                    transaction_state,
1417                    failure.error,
1418                    failure.poisoned,
1419                )
1420                .with_optional_cleanup(failure.cleanup)
1421            })?;
1422            Ok(Self::from_inner(SessionInner::CoordinatorNegotiating(
1423                Box::new(inner),
1424            )))
1425        }
1426        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1427        {
1428            let _ = command;
1429            Err(SessionFailure::new(
1430                SessionOperation::Spawn,
1431                SessionTransactionState::NotEstablished,
1432                SessionError::BackendUnavailable,
1433            ))
1434        }
1435    }
1436
1437    /// Peer HELLO application payload, available before the coordinator decides.
1438    pub fn peer_application_payload(&self) -> &[u8] {
1439        match &self.inner {
1440            #[cfg(target_os = "linux")]
1441            SessionInner::CoordinatorNegotiating(inner) => inner.peer_application_payload(),
1442            #[cfg(target_os = "macos")]
1443            SessionInner::CoordinatorNegotiating(inner) => inner.peer_application_payload(),
1444            #[cfg(target_os = "windows")]
1445            SessionInner::CoordinatorNegotiating(inner) => inner.peer_application_payload(),
1446            #[cfg(target_os = "linux")]
1447            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1448            #[cfg(target_os = "macos")]
1449            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1450            #[cfg(target_os = "windows")]
1451            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1452            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1453            SessionInner::Unavailable => {
1454                unreachable!("unavailable backend cannot construct a session")
1455            }
1456        }
1457    }
1458
1459    /// Makes the explicit coordinator decision and awaits the receiver decision.
1460    pub fn decide(
1461        self,
1462        decision: NegotiationDecision,
1463    ) -> Result<NegotiationOutcome<Session<Coordinator, Ready>>, SessionFailure> {
1464        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1465        let _ = decision;
1466        match self.inner {
1467            #[cfg(target_os = "linux")]
1468            SessionInner::CoordinatorNegotiating(inner) => {
1469                let outcome = inner
1470                    .decide(decision_rejection(decision))
1471                    .map_err(|failure| {
1472                        let native_code = linux_public_native_code(failure.error);
1473                        SessionFailure::new(
1474                            SessionOperation::Negotiate,
1475                            SessionTransactionState::Negotiating,
1476                            failure.error.into(),
1477                        )
1478                        .with_native_code(native_code)
1479                        .with_poisoned(failure.poisoned)
1480                        .with_optional_cleanup(failure.cleanup)
1481                    })?;
1482                map_linux_coordinator_outcome(outcome)
1483            }
1484            #[cfg(target_os = "macos")]
1485            SessionInner::CoordinatorNegotiating(inner) => {
1486                let outcome = inner
1487                    .decide(decision_rejection(decision))
1488                    .map_err(|failure| {
1489                        mac_session_failure(
1490                            SessionOperation::Negotiate,
1491                            SessionTransactionState::Negotiating,
1492                            failure.error,
1493                            failure.poisoned,
1494                        )
1495                        .with_optional_cleanup(failure.cleanup)
1496                    })?;
1497                map_mac_coordinator_outcome(outcome)
1498            }
1499            #[cfg(target_os = "windows")]
1500            SessionInner::CoordinatorNegotiating(inner) => {
1501                let outcome = (*inner)
1502                    .decide(decision_rejection(decision))
1503                    .map_err(|failure| {
1504                        windows_session_failure(
1505                            SessionOperation::Negotiate,
1506                            SessionTransactionState::Negotiating,
1507                            failure.error,
1508                            failure.poisoned,
1509                        )
1510                        .with_optional_cleanup(failure.cleanup)
1511                    })?;
1512                map_windows_coordinator_outcome(outcome)
1513            }
1514            #[cfg(target_os = "linux")]
1515            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1516            #[cfg(target_os = "macos")]
1517            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1518            #[cfg(target_os = "windows")]
1519            _ => unreachable!("coordinator negotiating typestate owns its exact backend state"),
1520            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1521            SessionInner::Unavailable => {
1522                unreachable!("unavailable backend cannot construct a session")
1523            }
1524        }
1525    }
1526}
1527
1528impl Session<Receiver, Negotiating> {
1529    /// Consumes the unique process-entry bootstrap and exchanges HELLOs.
1530    pub fn from_bootstrap(
1531        bootstrap: ReceiverBootstrap,
1532        options: SessionOptions,
1533    ) -> Result<Self, SessionFailure> {
1534        validate_public_options(&options).map_err(|reason| {
1535            SessionFailure::new(
1536                SessionOperation::Bootstrap,
1537                SessionTransactionState::NotEstablished,
1538                reason,
1539            )
1540        })?;
1541        #[cfg(target_os = "linux")]
1542        {
1543            let inner = crate::backend::linux_vnext::spawn::LinuxReceiverNegotiatingSession::from_inherited_bootstrap(
1544                bootstrap.inherited,
1545                options.limits,
1546                options.application_payload,
1547                options.require_atomic_u32,
1548                options.require_atomic_u64,
1549                options.deadline,
1550            )
1551            .map_err(|error| {
1552                SessionFailure::new(
1553                    SessionOperation::Bootstrap,
1554                    SessionTransactionState::Negotiating,
1555                    error.into(),
1556                )
1557                .with_native_code(linux_public_native_code(error))
1558                .with_poisoned(true)
1559            })?;
1560            Ok(Self::from_inner(SessionInner::ReceiverNegotiating(inner)))
1561        }
1562        #[cfg(target_os = "macos")]
1563        {
1564            let _bootstrap = bootstrap;
1565            let inner =
1566                crate::backend::macos::vnext_session::MacReceiverNegotiatingSession::from_environment(
1567                    options.limits,
1568                    options.application_payload,
1569                    options.require_atomic_u32,
1570                    options.require_atomic_u64,
1571                    options.deadline,
1572                )
1573                .map_err(|error| {
1574                    // Parity: an absent bootstrap designation or invalid
1575                    // caller input means no peer exists and nothing was
1576                    // negotiated, matching the Linux mapping.
1577                    let invalid_input = matches!(
1578                        error,
1579                        crate::backend::macos::vnext_session::MacPublicSessionError::InvalidInput
1580                    );
1581                    let state = if invalid_input {
1582                        SessionTransactionState::NotEstablished
1583                    } else {
1584                        SessionTransactionState::Negotiating
1585                    };
1586                    mac_session_failure(
1587                        SessionOperation::Bootstrap,
1588                        state,
1589                        error,
1590                        !invalid_input,
1591                    )
1592                })?;
1593            Ok(Self::from_inner(SessionInner::ReceiverNegotiating(inner)))
1594        }
1595        #[cfg(target_os = "windows")]
1596        {
1597            let _bootstrap = bootstrap;
1598            let inner = crate::backend::windows::vnext_session::WindowsReceiverNegotiatingSession::from_environment(&options)
1599            .map_err(|error| {
1600                // Parity: an absent bootstrap designation or invalid caller
1601                // input means no peer exists and nothing was negotiated,
1602                // matching the Linux mapping.
1603                let invalid_input = matches!(
1604                    error,
1605                    crate::backend::windows::vnext_session::WindowsPublicSessionError::InvalidInput
1606                );
1607                let state = if invalid_input {
1608                    SessionTransactionState::NotEstablished
1609                } else {
1610                    SessionTransactionState::Negotiating
1611                };
1612                windows_session_failure(
1613                    SessionOperation::Bootstrap,
1614                    state,
1615                    error,
1616                    !invalid_input,
1617                )
1618            })?;
1619            Ok(Self::from_inner(SessionInner::ReceiverNegotiating(
1620                Box::new(inner),
1621            )))
1622        }
1623        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1624        {
1625            let _ = bootstrap;
1626            Err(SessionFailure::new(
1627                SessionOperation::Bootstrap,
1628                SessionTransactionState::NotEstablished,
1629                SessionError::BackendUnavailable,
1630            ))
1631        }
1632    }
1633
1634    /// Peer HELLO application payload, available before awaiting the decision.
1635    pub fn peer_application_payload(&self) -> &[u8] {
1636        match &self.inner {
1637            #[cfg(target_os = "linux")]
1638            SessionInner::ReceiverNegotiating(inner) => inner.peer_application_payload(),
1639            #[cfg(target_os = "macos")]
1640            SessionInner::ReceiverNegotiating(inner) => inner.peer_application_payload(),
1641            #[cfg(target_os = "windows")]
1642            SessionInner::ReceiverNegotiating(inner) => inner.peer_application_payload(),
1643            #[cfg(target_os = "linux")]
1644            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1645            #[cfg(target_os = "macos")]
1646            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1647            #[cfg(target_os = "windows")]
1648            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1649            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1650            SessionInner::Unavailable => {
1651                unreachable!("unavailable backend cannot construct a session")
1652            }
1653        }
1654    }
1655
1656    /// Awaits exact coordinator ACCEPT before invoking the receiver decision.
1657    pub fn decide_after_coordinator(
1658        self,
1659        decide: impl FnOnce(&[u8]) -> NegotiationDecision,
1660    ) -> Result<NegotiationOutcome<Session<Receiver, Ready>>, SessionFailure> {
1661        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1662        let _ = decide;
1663        match self.inner {
1664            #[cfg(target_os = "linux")]
1665            SessionInner::ReceiverNegotiating(inner) => {
1666                let outcome = inner
1667                    .decide_after_coordinator(|payload| decision_rejection(decide(payload)))
1668                    .map_err(|error| {
1669                        SessionFailure::new(
1670                            SessionOperation::Negotiate,
1671                            SessionTransactionState::Negotiating,
1672                            error.into(),
1673                        )
1674                        .with_native_code(linux_public_native_code(error))
1675                        .with_poisoned(true)
1676                    })?;
1677                map_linux_receiver_outcome(outcome)
1678            }
1679            #[cfg(target_os = "macos")]
1680            SessionInner::ReceiverNegotiating(inner) => {
1681                let outcome = inner
1682                    .decide_after_coordinator(|payload| decision_rejection(decide(payload)))
1683                    .map_err(|error| {
1684                        mac_session_failure(
1685                            SessionOperation::Negotiate,
1686                            SessionTransactionState::Negotiating,
1687                            error,
1688                            true,
1689                        )
1690                    })?;
1691                map_mac_receiver_outcome(outcome)
1692            }
1693            #[cfg(target_os = "windows")]
1694            SessionInner::ReceiverNegotiating(inner) => {
1695                let outcome = (*inner)
1696                    .decide_after_coordinator(|payload| decision_rejection(decide(payload)))
1697                    .map_err(|error| {
1698                        windows_session_failure(
1699                            SessionOperation::Negotiate,
1700                            SessionTransactionState::Negotiating,
1701                            error,
1702                            true,
1703                        )
1704                    })?;
1705                map_windows_receiver_outcome(outcome)
1706            }
1707            #[cfg(target_os = "linux")]
1708            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1709            #[cfg(target_os = "macos")]
1710            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1711            #[cfg(target_os = "windows")]
1712            _ => unreachable!("receiver negotiating typestate owns its exact backend state"),
1713            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1714            SessionInner::Unavailable => {
1715                unreachable!("unavailable backend cannot construct a session")
1716            }
1717        }
1718    }
1719}
1720
1721impl Session<Coordinator, Ready> {
1722    #[cfg(all(test, target_os = "linux"))]
1723    pub(crate) fn fail_next_cleanup_signal_for_test(&self, code: i32) {
1724        match &self.inner {
1725            SessionInner::CoordinatorReady(inner) => {
1726                inner.fail_next_cleanup_signal_for_test(code);
1727            }
1728            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1729        }
1730    }
1731
1732    /// Effective finite limits bound into the accepted transcript.
1733    pub fn negotiated_limits(&self) -> SessionLimits {
1734        match &self.inner {
1735            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1736            SessionInner::CoordinatorReady(inner) => inner.limits(),
1737            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1738            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1739            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1740            SessionInner::Unavailable => {
1741                unreachable!("unavailable backend cannot construct a session")
1742            }
1743        }
1744    }
1745
1746    /// Effective lock-free atomic and layout alignment facts bound into ACCEPT.
1747    pub fn atomic_capabilities(&self) -> AtomicCapabilities {
1748        match &self.inner {
1749            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1750            SessionInner::CoordinatorReady(inner) => inner.atomics(),
1751            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1752            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1753            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1754            SessionInner::Unavailable => {
1755                unreachable!("unavailable backend cannot construct a session")
1756            }
1757        }
1758    }
1759
1760    /// Accepted protocol version from the exact challenged transcript.
1761    pub fn protocol_version(&self) -> ProtocolVersion {
1762        match &self.inner {
1763            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1764            SessionInner::CoordinatorReady(inner) => inner.protocol_version(),
1765            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1766            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1767            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1768            SessionInner::Unavailable => {
1769                unreachable!("unavailable backend cannot construct a session")
1770            }
1771        }
1772    }
1773
1774    /// Current local reducer/liveness state.
1775    pub fn state(&self) -> SessionState {
1776        match &self.inner {
1777            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1778            SessionInner::CoordinatorReady(inner) => inner.state(),
1779            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1780            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1781            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1782            SessionInner::Unavailable => {
1783                unreachable!("unavailable backend cannot construct a session")
1784            }
1785        }
1786    }
1787
1788    /// Bounded current active-mapping lease counters.
1789    pub fn active_leases(&self) -> ActiveLeaseFacts {
1790        match &self.inner {
1791            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1792            SessionInner::CoordinatorReady(inner) => inner.active_leases(),
1793            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1794            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1795            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1796            SessionInner::Unavailable => {
1797                unreachable!("unavailable backend cannot construct a session")
1798            }
1799        }
1800    }
1801
1802    /// Performs one nonblocking authenticated peer observation.
1803    pub fn poll_peer(&mut self) -> Result<PeerStatus, SessionFailure> {
1804        match &mut self.inner {
1805            #[cfg(target_os = "linux")]
1806            SessionInner::CoordinatorReady(inner) => {
1807                let result = inner.poll_peer();
1808                let state = inner.state();
1809                result
1810                    .map_err(|error| linux_ready_failure(SessionOperation::PollPeer, state, error))
1811            }
1812            #[cfg(target_os = "macos")]
1813            SessionInner::CoordinatorReady(inner) => {
1814                let result = inner.poll_peer();
1815                let state = inner.state();
1816                result.map_err(|error| mac_ready_failure(SessionOperation::PollPeer, state, error))
1817            }
1818            #[cfg(target_os = "windows")]
1819            SessionInner::CoordinatorReady(inner) => {
1820                let result = inner.poll_peer();
1821                let state = inner.state();
1822                result.map_err(|error| {
1823                    windows_ready_failure(SessionOperation::PollPeer, state, error)
1824                })
1825            }
1826            #[cfg(target_os = "linux")]
1827            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1828            #[cfg(target_os = "macos")]
1829            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1830            #[cfg(target_os = "windows")]
1831            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1832            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1833            SessionInner::Unavailable => Err(SessionFailure::new(
1834                SessionOperation::PollPeer,
1835                SessionTransactionState::NotEstablished,
1836                SessionError::BackendUnavailable,
1837            )),
1838        }
1839    }
1840
1841    /// Boundedly waits for and reaps the exact direct child without consuming the session.
1842    pub fn wait_for_exit(&mut self, deadline: AbsoluteDeadline) -> ChildCleanupFacts {
1843        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1844        let _ = deadline;
1845        match &mut self.inner {
1846            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1847            SessionInner::CoordinatorReady(inner) => inner.wait_for_exit(deadline),
1848            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1849            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1850            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1851            SessionInner::Unavailable => {
1852                ChildCleanupFacts::new(None, DescendantCleanupStatus::NotEstablished, None)
1853            }
1854        }
1855    }
1856
1857    /// Gracefully closes only after active leases are gone and the exact child is reaped.
1858    pub fn try_close(mut self, deadline: AbsoluteDeadline) -> CoordinatorCloseOutcome {
1859        let facts = self.active_leases();
1860        if !facts.is_empty() {
1861            return CoordinatorCloseOutcome::ActiveLeases {
1862                session: self,
1863                facts,
1864            };
1865        }
1866        let cleanup = self.wait_for_exit(deadline);
1867        if !cleanup.direct_child_complete() {
1868            let reason = if cleanup.native_error().is_some() {
1869                SessionError::Native
1870            } else {
1871                SessionError::DeadlineExpired
1872            };
1873            let failure = SessionFailure::new(
1874                SessionOperation::Close,
1875                if self.state() == SessionState::Poisoned {
1876                    SessionTransactionState::Poisoned
1877                } else {
1878                    SessionTransactionState::Ready
1879                },
1880                reason,
1881            )
1882            .with_native_code(cleanup.native_error())
1883            .with_poisoned(self.state() == SessionState::Poisoned)
1884            .with_cleanup(cleanup);
1885            return CoordinatorCloseOutcome::CleanupPending {
1886                session: self,
1887                facts: cleanup,
1888                failure,
1889            };
1890        }
1891        let close: Result<(), SessionFailure> = match &mut self.inner {
1892            #[cfg(target_os = "linux")]
1893            SessionInner::CoordinatorReady(inner) => {
1894                let result = inner.close_resources();
1895                let state = inner.state();
1896                result.map_err(|error| {
1897                    linux_ready_failure(SessionOperation::Close, state, error).with_cleanup(cleanup)
1898                })
1899            }
1900            #[cfg(target_os = "macos")]
1901            SessionInner::CoordinatorReady(inner) => {
1902                let result = inner.close_resources();
1903                let state = inner.state();
1904                result.map_err(|error| {
1905                    mac_ready_failure(SessionOperation::Close, state, error).with_cleanup(cleanup)
1906                })
1907            }
1908            #[cfg(target_os = "windows")]
1909            SessionInner::CoordinatorReady(inner) => {
1910                let result = inner.close_resources();
1911                let state = inner.state();
1912                result.map_err(|error| {
1913                    windows_ready_failure(SessionOperation::Close, state, error)
1914                        .with_cleanup(cleanup)
1915                })
1916            }
1917            #[cfg(target_os = "linux")]
1918            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1919            #[cfg(target_os = "macos")]
1920            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1921            #[cfg(target_os = "windows")]
1922            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1923            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1924            SessionInner::Unavailable => Err(SessionFailure::new(
1925                SessionOperation::Close,
1926                SessionTransactionState::NotEstablished,
1927                SessionError::BackendUnavailable,
1928            )
1929            .with_cleanup(cleanup)),
1930        };
1931        if let Err(error) = close {
1932            return CoordinatorCloseOutcome::Failed {
1933                session: self,
1934                error,
1935            };
1936        }
1937        CoordinatorCloseOutcome::Closed(cleanup)
1938    }
1939
1940    /// Terminally poisons live mappings, terminates the exact child, and returns cleanup facts.
1941    pub fn abort(mut self, deadline: AbsoluteDeadline) -> CoordinatorAbortOutcome {
1942        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1943        let _ = deadline;
1944        let cleanup = match &mut self.inner {
1945            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1946            SessionInner::CoordinatorReady(inner) => inner.abort(deadline),
1947            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
1948            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
1949            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1950            SessionInner::Unavailable => {
1951                ChildCleanupFacts::new(None, DescendantCleanupStatus::NotEstablished, None)
1952            }
1953        };
1954        let failure = if cleanup.direct_child_complete() {
1955            None
1956        } else {
1957            let reason = if cleanup.native_error().is_some() {
1958                SessionError::Native
1959            } else {
1960                SessionError::DeadlineExpired
1961            };
1962            Some(
1963                SessionFailure::new(
1964                    SessionOperation::Abort,
1965                    SessionTransactionState::Poisoned,
1966                    reason,
1967                )
1968                .with_native_code(cleanup.native_error())
1969                .with_poisoned(true)
1970                .with_cleanup(cleanup),
1971            )
1972        };
1973        CoordinatorAbortOutcome { cleanup, failure }
1974    }
1975
1976    /// Starts a local batch builder bounded by this accepted session.
1977    pub fn new_transfer_batch(&self) -> Result<TransferBatch, BatchError> {
1978        let limits = self.negotiated_limits();
1979        TransferBatch::new(
1980            limits.max_regions_per_batch,
1981            limits.max_region_bytes,
1982            limits.max_batch_bytes,
1983        )
1984    }
1985
1986    /// Completes one atomic capability transaction and activates its full set.
1987    pub fn transfer_batch(
1988        &mut self,
1989        batch: TransferBatch,
1990        deadline: AbsoluteDeadline,
1991    ) -> Result<ActiveRegionSet, SessionFailure> {
1992        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
1993        let _ = (batch, deadline);
1994        match &mut self.inner {
1995            #[cfg(target_os = "linux")]
1996            SessionInner::CoordinatorReady(inner) => {
1997                let result = inner.transfer_batch(batch, deadline);
1998                let state = inner.state();
1999                result.map_err(|error| {
2000                    linux_ready_batch_failure(SessionOperation::TransferBatch, state, error)
2001                })
2002            }
2003            #[cfg(target_os = "macos")]
2004            SessionInner::CoordinatorReady(inner) => {
2005                let result = inner.transfer_batch(batch, deadline);
2006                let state = inner.state();
2007                result.map_err(|error| {
2008                    mac_ready_failure(SessionOperation::TransferBatch, state, error)
2009                })
2010            }
2011            #[cfg(target_os = "windows")]
2012            SessionInner::CoordinatorReady(inner) => {
2013                let result = inner.transfer_batch(batch, deadline);
2014                let state = inner.state();
2015                result.map_err(|error| {
2016                    windows_ready_failure(SessionOperation::TransferBatch, state, error)
2017                })
2018            }
2019            #[cfg(target_os = "linux")]
2020            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2021            #[cfg(target_os = "macos")]
2022            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2023            #[cfg(target_os = "windows")]
2024            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2025            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2026            SessionInner::Unavailable => {
2027                unreachable!("unavailable backend cannot construct a session")
2028            }
2029        }
2030    }
2031
2032    /// Sends one bounded opaque application record under the supplied deadline.
2033    pub fn send_control(
2034        &mut self,
2035        kind: u32,
2036        payload: &[u8],
2037        deadline: AbsoluteDeadline,
2038    ) -> Result<(), SessionFailure> {
2039        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2040        let _ = (kind, payload, deadline);
2041        match &mut self.inner {
2042            #[cfg(target_os = "linux")]
2043            SessionInner::CoordinatorReady(inner) => {
2044                let result = inner.send_control(kind, payload, deadline);
2045                let state = inner.state();
2046                result.map_err(|error| {
2047                    linux_ready_failure(SessionOperation::SendControl, state, error)
2048                })
2049            }
2050            #[cfg(target_os = "macos")]
2051            SessionInner::CoordinatorReady(inner) => {
2052                let result = inner.send_control(kind, payload, deadline);
2053                let state = inner.state();
2054                result
2055                    .map_err(|error| mac_ready_failure(SessionOperation::SendControl, state, error))
2056            }
2057            #[cfg(target_os = "windows")]
2058            SessionInner::CoordinatorReady(inner) => {
2059                let result = inner.send_control(kind, payload, deadline);
2060                let state = inner.state();
2061                result.map_err(|error| {
2062                    windows_ready_failure(SessionOperation::SendControl, state, error)
2063                })
2064            }
2065            #[cfg(target_os = "linux")]
2066            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2067            #[cfg(target_os = "macos")]
2068            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2069            #[cfg(target_os = "windows")]
2070            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2071            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2072            SessionInner::Unavailable => {
2073                unreachable!("unavailable backend cannot construct a session")
2074            }
2075        }
2076    }
2077
2078    /// Receives one bounded opaque peer record under the supplied deadline.
2079    pub fn receive_control(
2080        &mut self,
2081        deadline: AbsoluteDeadline,
2082    ) -> Result<ControlFrame, SessionFailure> {
2083        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2084        let _ = deadline;
2085        match &mut self.inner {
2086            #[cfg(target_os = "linux")]
2087            SessionInner::CoordinatorReady(inner) => {
2088                let result = inner.receive_control(deadline);
2089                let state = inner.state();
2090                result.map_err(|error| {
2091                    linux_ready_failure(SessionOperation::ReceiveControl, state, error)
2092                })
2093            }
2094            #[cfg(target_os = "macos")]
2095            SessionInner::CoordinatorReady(inner) => {
2096                let result = inner.receive_control(deadline);
2097                let state = inner.state();
2098                result.map_err(|error| {
2099                    mac_ready_failure(SessionOperation::ReceiveControl, state, error)
2100                })
2101            }
2102            #[cfg(target_os = "windows")]
2103            SessionInner::CoordinatorReady(inner) => {
2104                let result = inner.receive_control(deadline);
2105                let state = inner.state();
2106                result.map_err(|error| {
2107                    windows_ready_failure(SessionOperation::ReceiveControl, state, error)
2108                })
2109            }
2110            #[cfg(target_os = "linux")]
2111            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2112            #[cfg(target_os = "macos")]
2113            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2114            #[cfg(target_os = "windows")]
2115            _ => unreachable!("coordinator ready typestate owns its exact backend state"),
2116            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2117            SessionInner::Unavailable => {
2118                unreachable!("unavailable backend cannot construct a session")
2119            }
2120        }
2121    }
2122}
2123
2124impl Session<Receiver, Ready> {
2125    /// Effective finite limits bound into the accepted transcript.
2126    pub fn negotiated_limits(&self) -> SessionLimits {
2127        match &self.inner {
2128            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2129            SessionInner::ReceiverReady(inner) => inner.limits(),
2130            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2131            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2132            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2133            SessionInner::Unavailable => {
2134                unreachable!("unavailable backend cannot construct a session")
2135            }
2136        }
2137    }
2138
2139    /// Effective lock-free atomic and layout alignment facts bound into ACCEPT.
2140    pub fn atomic_capabilities(&self) -> AtomicCapabilities {
2141        match &self.inner {
2142            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2143            SessionInner::ReceiverReady(inner) => inner.atomics(),
2144            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2145            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2146            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2147            SessionInner::Unavailable => {
2148                unreachable!("unavailable backend cannot construct a session")
2149            }
2150        }
2151    }
2152
2153    /// Accepted protocol version from the exact challenged transcript.
2154    pub fn protocol_version(&self) -> ProtocolVersion {
2155        match &self.inner {
2156            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2157            SessionInner::ReceiverReady(inner) => inner.protocol_version(),
2158            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2159            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2160            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2161            SessionInner::Unavailable => {
2162                unreachable!("unavailable backend cannot construct a session")
2163            }
2164        }
2165    }
2166
2167    /// Current local reducer/liveness state.
2168    pub fn state(&self) -> SessionState {
2169        match &self.inner {
2170            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2171            SessionInner::ReceiverReady(inner) => inner.state(),
2172            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2173            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2174            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2175            SessionInner::Unavailable => {
2176                unreachable!("unavailable backend cannot construct a session")
2177            }
2178        }
2179    }
2180
2181    /// Bounded current active-mapping lease counters.
2182    pub fn active_leases(&self) -> ActiveLeaseFacts {
2183        match &self.inner {
2184            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2185            SessionInner::ReceiverReady(inner) => inner.active_leases(),
2186            #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2187            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2188            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2189            SessionInner::Unavailable => {
2190                unreachable!("unavailable backend cannot construct a session")
2191            }
2192        }
2193    }
2194
2195    /// Performs one nonblocking authenticated peer observation.
2196    pub fn poll_peer(&mut self) -> Result<PeerStatus, SessionFailure> {
2197        match &mut self.inner {
2198            #[cfg(target_os = "linux")]
2199            SessionInner::ReceiverReady(inner) => {
2200                let result = inner.poll_peer();
2201                let state = inner.state();
2202                result
2203                    .map_err(|error| linux_ready_failure(SessionOperation::PollPeer, state, error))
2204            }
2205            #[cfg(target_os = "macos")]
2206            SessionInner::ReceiverReady(inner) => {
2207                let result = inner.poll_peer();
2208                let state = inner.state();
2209                result.map_err(|error| mac_ready_failure(SessionOperation::PollPeer, state, error))
2210            }
2211            #[cfg(target_os = "windows")]
2212            SessionInner::ReceiverReady(inner) => {
2213                let result = inner.poll_peer();
2214                let state = inner.state();
2215                result.map_err(|error| {
2216                    windows_ready_failure(SessionOperation::PollPeer, state, error)
2217                })
2218            }
2219            #[cfg(target_os = "linux")]
2220            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2221            #[cfg(target_os = "macos")]
2222            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2223            #[cfg(target_os = "windows")]
2224            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2225            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2226            SessionInner::Unavailable => Err(SessionFailure::new(
2227                SessionOperation::PollPeer,
2228                SessionTransactionState::NotEstablished,
2229                SessionError::BackendUnavailable,
2230            )),
2231        }
2232    }
2233
2234    /// Boundedly waits for authenticated peer endpoint closure under one deadline.
2235    pub fn wait_for_exit(
2236        &mut self,
2237        deadline: AbsoluteDeadline,
2238    ) -> Result<PeerStatus, SessionFailure> {
2239        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2240        let _ = deadline;
2241        match &mut self.inner {
2242            #[cfg(target_os = "linux")]
2243            SessionInner::ReceiverReady(inner) => {
2244                let result = inner.wait_for_exit(deadline);
2245                let state = inner.state();
2246                result.map_err(|error| {
2247                    linux_ready_failure(SessionOperation::WaitForExit, state, error)
2248                })
2249            }
2250            #[cfg(target_os = "macos")]
2251            SessionInner::ReceiverReady(inner) => {
2252                let result = inner.wait_for_exit(deadline);
2253                let state = inner.state();
2254                result
2255                    .map_err(|error| mac_ready_failure(SessionOperation::WaitForExit, state, error))
2256            }
2257            #[cfg(target_os = "windows")]
2258            SessionInner::ReceiverReady(inner) => {
2259                let result = inner.wait_for_exit(deadline);
2260                let state = inner.state();
2261                result.map_err(|error| {
2262                    windows_ready_failure(SessionOperation::WaitForExit, state, error)
2263                })
2264            }
2265            #[cfg(target_os = "linux")]
2266            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2267            #[cfg(target_os = "macos")]
2268            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2269            #[cfg(target_os = "windows")]
2270            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2271            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2272            SessionInner::Unavailable => Err(SessionFailure::new(
2273                SessionOperation::WaitForExit,
2274                SessionTransactionState::NotEstablished,
2275                SessionError::BackendUnavailable,
2276            )),
2277        }
2278    }
2279
2280    /// Closes the inherited endpoint only after every active mapping lease is gone.
2281    pub fn try_close(mut self) -> ReceiverCloseOutcome {
2282        let facts = self.active_leases();
2283        if !facts.is_empty() {
2284            return ReceiverCloseOutcome::ActiveLeases {
2285                session: self,
2286                facts,
2287            };
2288        }
2289        let close: Result<(), SessionFailure> = match &mut self.inner {
2290            #[cfg(target_os = "linux")]
2291            SessionInner::ReceiverReady(inner) => {
2292                let result = inner.close_resources();
2293                let state = inner.state();
2294                result.map_err(|error| linux_ready_failure(SessionOperation::Close, state, error))
2295            }
2296            #[cfg(target_os = "macos")]
2297            SessionInner::ReceiverReady(inner) => {
2298                let result = inner.close_resources();
2299                let state = inner.state();
2300                result.map_err(|error| mac_ready_failure(SessionOperation::Close, state, error))
2301            }
2302            #[cfg(target_os = "windows")]
2303            SessionInner::ReceiverReady(inner) => {
2304                let result = inner.close_resources();
2305                let state = inner.state();
2306                result.map_err(|error| windows_ready_failure(SessionOperation::Close, state, error))
2307            }
2308            #[cfg(target_os = "linux")]
2309            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2310            #[cfg(target_os = "macos")]
2311            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2312            #[cfg(target_os = "windows")]
2313            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2314            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2315            SessionInner::Unavailable => Err(SessionFailure::new(
2316                SessionOperation::Close,
2317                SessionTransactionState::NotEstablished,
2318                SessionError::BackendUnavailable,
2319            )),
2320        };
2321        if let Err(error) = close {
2322            return ReceiverCloseOutcome::Failed {
2323                session: self,
2324                error,
2325            };
2326        }
2327        ReceiverCloseOutcome::Closed
2328    }
2329
2330    /// Terminally poisons every live mapping and closes the inherited endpoint.
2331    pub fn abort(mut self) {
2332        match &mut self.inner {
2333            #[cfg(target_os = "linux")]
2334            SessionInner::ReceiverReady(inner) => inner.abort(),
2335            #[cfg(target_os = "macos")]
2336            SessionInner::ReceiverReady(inner) => inner.abort(),
2337            #[cfg(target_os = "windows")]
2338            SessionInner::ReceiverReady(inner) => inner.abort(),
2339            #[cfg(target_os = "linux")]
2340            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2341            #[cfg(target_os = "macos")]
2342            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2343            #[cfg(target_os = "windows")]
2344            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2345            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2346            SessionInner::Unavailable => {}
2347        }
2348    }
2349
2350    /// Receives, validates, commits, and activates one exact expected batch.
2351    pub fn receive_batch(
2352        &mut self,
2353        expected: ExpectedBatch,
2354        deadline: AbsoluteDeadline,
2355    ) -> Result<ActiveRegionSet, SessionFailure> {
2356        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2357        let _ = (expected, deadline);
2358        match &mut self.inner {
2359            #[cfg(target_os = "linux")]
2360            SessionInner::ReceiverReady(inner) => {
2361                let result = inner.receive_batch(expected, deadline);
2362                let state = inner.state();
2363                result.map_err(|error| {
2364                    linux_ready_batch_failure(SessionOperation::ReceiveBatch, state, error)
2365                })
2366            }
2367            #[cfg(target_os = "macos")]
2368            SessionInner::ReceiverReady(inner) => {
2369                let result = inner.receive_batch(expected, deadline);
2370                let state = inner.state();
2371                result.map_err(|error| {
2372                    mac_ready_failure(SessionOperation::ReceiveBatch, state, error)
2373                })
2374            }
2375            #[cfg(target_os = "windows")]
2376            SessionInner::ReceiverReady(inner) => {
2377                let result = inner.receive_batch(expected, deadline);
2378                let state = inner.state();
2379                result.map_err(|error| {
2380                    windows_ready_failure(SessionOperation::ReceiveBatch, state, error)
2381                })
2382            }
2383            #[cfg(target_os = "linux")]
2384            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2385            #[cfg(target_os = "macos")]
2386            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2387            #[cfg(target_os = "windows")]
2388            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2389            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2390            SessionInner::Unavailable => {
2391                unreachable!("unavailable backend cannot construct a session")
2392            }
2393        }
2394    }
2395
2396    /// Sends one bounded opaque application record under the supplied deadline.
2397    pub fn send_control(
2398        &mut self,
2399        kind: u32,
2400        payload: &[u8],
2401        deadline: AbsoluteDeadline,
2402    ) -> Result<(), SessionFailure> {
2403        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2404        let _ = (kind, payload, deadline);
2405        match &mut self.inner {
2406            #[cfg(target_os = "linux")]
2407            SessionInner::ReceiverReady(inner) => {
2408                let result = inner.send_control(kind, payload, deadline);
2409                let state = inner.state();
2410                result.map_err(|error| {
2411                    linux_ready_failure(SessionOperation::SendControl, state, error)
2412                })
2413            }
2414            #[cfg(target_os = "macos")]
2415            SessionInner::ReceiverReady(inner) => {
2416                let result = inner.send_control(kind, payload, deadline);
2417                let state = inner.state();
2418                result
2419                    .map_err(|error| mac_ready_failure(SessionOperation::SendControl, state, error))
2420            }
2421            #[cfg(target_os = "windows")]
2422            SessionInner::ReceiverReady(inner) => {
2423                let result = inner.send_control(kind, payload, deadline);
2424                let state = inner.state();
2425                result.map_err(|error| {
2426                    windows_ready_failure(SessionOperation::SendControl, state, error)
2427                })
2428            }
2429            #[cfg(target_os = "linux")]
2430            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2431            #[cfg(target_os = "macos")]
2432            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2433            #[cfg(target_os = "windows")]
2434            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2435            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2436            SessionInner::Unavailable => {
2437                unreachable!("unavailable backend cannot construct a session")
2438            }
2439        }
2440    }
2441
2442    /// Receives one bounded opaque peer record under the supplied deadline.
2443    pub fn receive_control(
2444        &mut self,
2445        deadline: AbsoluteDeadline,
2446    ) -> Result<ControlFrame, SessionFailure> {
2447        #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2448        let _ = deadline;
2449        match &mut self.inner {
2450            #[cfg(target_os = "linux")]
2451            SessionInner::ReceiverReady(inner) => {
2452                let result = inner.receive_control(deadline);
2453                let state = inner.state();
2454                result.map_err(|error| {
2455                    linux_ready_failure(SessionOperation::ReceiveControl, state, error)
2456                })
2457            }
2458            #[cfg(target_os = "macos")]
2459            SessionInner::ReceiverReady(inner) => {
2460                let result = inner.receive_control(deadline);
2461                let state = inner.state();
2462                result.map_err(|error| {
2463                    mac_ready_failure(SessionOperation::ReceiveControl, state, error)
2464                })
2465            }
2466            #[cfg(target_os = "windows")]
2467            SessionInner::ReceiverReady(inner) => {
2468                let result = inner.receive_control(deadline);
2469                let state = inner.state();
2470                result.map_err(|error| {
2471                    windows_ready_failure(SessionOperation::ReceiveControl, state, error)
2472                })
2473            }
2474            #[cfg(target_os = "linux")]
2475            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2476            #[cfg(target_os = "macos")]
2477            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2478            #[cfg(target_os = "windows")]
2479            _ => unreachable!("receiver ready typestate owns its exact backend state"),
2480            #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
2481            SessionInner::Unavailable => {
2482                unreachable!("unavailable backend cannot construct a session")
2483            }
2484        }
2485    }
2486}
2487
2488fn validate_public_options(options: &SessionOptions) -> Result<(), SessionError> {
2489    if options.deadline.is_expired()
2490        || options.application_payload.len() > options.limits.max_bootstrap_payload_bytes as usize
2491    {
2492        return Err(if options.deadline.is_expired() {
2493            SessionError::DeadlineExpired
2494        } else {
2495            SessionError::InvalidInput
2496        });
2497    }
2498    match options.executable_identity {
2499        ExecutableIdentityPolicy::ExactOpenedFile => {}
2500    }
2501    options
2502        .limits
2503        .validate()
2504        .map(|_| ())
2505        .map_err(SessionError::NativeNegotiation)
2506}
2507
2508#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
2509const fn decision_rejection(decision: NegotiationDecision) -> Option<NonZeroU32> {
2510    match decision {
2511        NegotiationDecision::Accept => None,
2512        NegotiationDecision::Reject(reason) => Some(reason.as_nonzero()),
2513    }
2514}
2515
2516#[cfg(target_os = "macos")]
2517fn map_mac_role(role: crate::backend::macos::vnext_session::MacNegotiationRole) -> SessionEndpoint {
2518    match role {
2519        crate::backend::macos::vnext_session::MacNegotiationRole::Coordinator => {
2520            SessionEndpoint::Coordinator
2521        }
2522        crate::backend::macos::vnext_session::MacNegotiationRole::Receiver => {
2523            SessionEndpoint::Receiver
2524        }
2525    }
2526}
2527
2528#[cfg(target_os = "macos")]
2529fn map_mac_coordinator_outcome(
2530    outcome: crate::backend::macos::vnext_session::MacNegotiationOutcome<
2531        crate::backend::macos::vnext_session::MacCoordinatorReadySession,
2532    >,
2533) -> Result<NegotiationOutcome<Session<Coordinator, Ready>>, SessionFailure> {
2534    match outcome {
2535        crate::backend::macos::vnext_session::MacNegotiationOutcome::Accepted(inner) => {
2536            Ok(NegotiationOutcome::Accepted(Session::from_inner(
2537                SessionInner::CoordinatorReady(inner),
2538            )))
2539        }
2540        crate::backend::macos::vnext_session::MacNegotiationOutcome::Rejected {
2541            by,
2542            reason,
2543            cleanup,
2544        } => {
2545            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2546                let failure = SessionFailure::new(
2547                    SessionOperation::Negotiate,
2548                    SessionTransactionState::Poisoned,
2549                    SessionError::MalformedPeer,
2550                );
2551                cleanup.map_or(failure, |facts| failure.with_cleanup(facts))
2552            })?;
2553            Ok(NegotiationOutcome::Rejected {
2554                by: map_mac_role(by),
2555                reason,
2556                cleanup,
2557            })
2558        }
2559    }
2560}
2561
2562#[cfg(target_os = "macos")]
2563fn map_mac_receiver_outcome(
2564    outcome: crate::backend::macos::vnext_session::MacNegotiationOutcome<
2565        crate::backend::macos::vnext_session::MacReceiverReadySession,
2566    >,
2567) -> Result<NegotiationOutcome<Session<Receiver, Ready>>, SessionFailure> {
2568    match outcome {
2569        crate::backend::macos::vnext_session::MacNegotiationOutcome::Accepted(inner) => Ok(
2570            NegotiationOutcome::Accepted(Session::from_inner(SessionInner::ReceiverReady(inner))),
2571        ),
2572        crate::backend::macos::vnext_session::MacNegotiationOutcome::Rejected {
2573            by,
2574            reason,
2575            cleanup,
2576        } => {
2577            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2578                SessionFailure::new(
2579                    SessionOperation::Negotiate,
2580                    SessionTransactionState::Poisoned,
2581                    SessionError::MalformedPeer,
2582                )
2583            })?;
2584            Ok(NegotiationOutcome::Rejected {
2585                by: map_mac_role(by),
2586                reason,
2587                cleanup,
2588            })
2589        }
2590    }
2591}
2592
2593#[cfg(target_os = "windows")]
2594fn map_windows_role(
2595    role: crate::backend::windows::vnext_session::WindowsNegotiationRole,
2596) -> SessionEndpoint {
2597    match role {
2598        crate::backend::windows::vnext_session::WindowsNegotiationRole::Coordinator => {
2599            SessionEndpoint::Coordinator
2600        }
2601        crate::backend::windows::vnext_session::WindowsNegotiationRole::Receiver => {
2602            SessionEndpoint::Receiver
2603        }
2604    }
2605}
2606
2607#[cfg(target_os = "windows")]
2608fn map_windows_coordinator_outcome(
2609    outcome: crate::backend::windows::vnext_session::WindowsNegotiationOutcome<
2610        crate::backend::windows::vnext_session::WindowsCoordinatorReadySession,
2611    >,
2612) -> Result<NegotiationOutcome<Session<Coordinator, Ready>>, SessionFailure> {
2613    match outcome {
2614        crate::backend::windows::vnext_session::WindowsNegotiationOutcome::Accepted(inner) => {
2615            Ok(NegotiationOutcome::Accepted(Session::from_inner(
2616                SessionInner::CoordinatorReady(Box::new(inner)),
2617            )))
2618        }
2619        crate::backend::windows::vnext_session::WindowsNegotiationOutcome::Rejected {
2620            by,
2621            reason,
2622            cleanup,
2623        } => {
2624            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2625                let failure = SessionFailure::new(
2626                    SessionOperation::Negotiate,
2627                    SessionTransactionState::Poisoned,
2628                    SessionError::MalformedPeer,
2629                );
2630                cleanup.map_or(failure, |facts| failure.with_cleanup(facts))
2631            })?;
2632            Ok(NegotiationOutcome::Rejected {
2633                by: map_windows_role(by),
2634                reason,
2635                cleanup,
2636            })
2637        }
2638    }
2639}
2640
2641#[cfg(target_os = "windows")]
2642fn map_windows_receiver_outcome(
2643    outcome: crate::backend::windows::vnext_session::WindowsNegotiationOutcome<
2644        crate::backend::windows::vnext_session::WindowsReceiverReadySession,
2645    >,
2646) -> Result<NegotiationOutcome<Session<Receiver, Ready>>, SessionFailure> {
2647    match outcome {
2648        crate::backend::windows::vnext_session::WindowsNegotiationOutcome::Accepted(inner) => {
2649            Ok(NegotiationOutcome::Accepted(Session::from_inner(
2650                SessionInner::ReceiverReady(Box::new(inner)),
2651            )))
2652        }
2653        crate::backend::windows::vnext_session::WindowsNegotiationOutcome::Rejected {
2654            by,
2655            reason,
2656            cleanup,
2657        } => {
2658            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2659                SessionFailure::new(
2660                    SessionOperation::Negotiate,
2661                    SessionTransactionState::Poisoned,
2662                    SessionError::MalformedPeer,
2663                )
2664            })?;
2665            Ok(NegotiationOutcome::Rejected {
2666                by: map_windows_role(by),
2667                reason,
2668                cleanup,
2669            })
2670        }
2671    }
2672}
2673
2674#[cfg(target_os = "linux")]
2675fn map_linux_role(
2676    role: crate::backend::linux_vnext::spawn::LinuxNegotiationRole,
2677) -> SessionEndpoint {
2678    match role {
2679        crate::backend::linux_vnext::spawn::LinuxNegotiationRole::Coordinator => {
2680            SessionEndpoint::Coordinator
2681        }
2682        crate::backend::linux_vnext::spawn::LinuxNegotiationRole::Receiver => {
2683            SessionEndpoint::Receiver
2684        }
2685    }
2686}
2687
2688#[cfg(target_os = "linux")]
2689fn map_linux_coordinator_outcome(
2690    outcome: crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome<
2691        crate::backend::linux_vnext::spawn::LinuxCoordinatorReadySession,
2692    >,
2693) -> Result<NegotiationOutcome<Session<Coordinator, Ready>>, SessionFailure> {
2694    match outcome {
2695        crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome::Accepted(inner) => {
2696            Ok(NegotiationOutcome::Accepted(Session::from_inner(
2697                SessionInner::CoordinatorReady(inner),
2698            )))
2699        }
2700        crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome::Rejected {
2701            by,
2702            reason,
2703            cleanup,
2704        } => {
2705            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2706                let failure = SessionFailure::new(
2707                    SessionOperation::Negotiate,
2708                    SessionTransactionState::Poisoned,
2709                    SessionError::MalformedPeer,
2710                );
2711                cleanup.map_or(failure, |facts| failure.with_cleanup(facts))
2712            })?;
2713            Ok(NegotiationOutcome::Rejected {
2714                by: map_linux_role(by),
2715                reason,
2716                cleanup,
2717            })
2718        }
2719    }
2720}
2721
2722#[cfg(target_os = "linux")]
2723fn map_linux_receiver_outcome(
2724    outcome: crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome<
2725        crate::backend::linux_vnext::spawn::LinuxReceiverReadySession,
2726    >,
2727) -> Result<NegotiationOutcome<Session<Receiver, Ready>>, SessionFailure> {
2728    match outcome {
2729        crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome::Accepted(inner) => Ok(
2730            NegotiationOutcome::Accepted(Session::from_inner(SessionInner::ReceiverReady(inner))),
2731        ),
2732        crate::backend::linux_vnext::spawn::LinuxNegotiationOutcome::Rejected {
2733            by,
2734            reason,
2735            cleanup,
2736        } => {
2737            let reason = RejectionReason::from_wire(reason).ok_or_else(|| {
2738                SessionFailure::new(
2739                    SessionOperation::Negotiate,
2740                    SessionTransactionState::Poisoned,
2741                    SessionError::MalformedPeer,
2742                )
2743            })?;
2744            Ok(NegotiationOutcome::Rejected {
2745                by: map_linux_role(by),
2746                reason,
2747                cleanup,
2748            })
2749        }
2750    }
2751}
2752
2753#[cfg(target_os = "linux")]
2754fn linux_ready_failure(
2755    operation: SessionOperation,
2756    state: SessionState,
2757    error: crate::backend::linux_vnext::spawn::LinuxPublicSessionError,
2758) -> SessionFailure {
2759    let native_code = linux_public_native_code(error);
2760    let poisoned = state == SessionState::Poisoned;
2761    SessionFailure::new(
2762        operation,
2763        if poisoned {
2764            SessionTransactionState::Poisoned
2765        } else {
2766            SessionTransactionState::Ready
2767        },
2768        error.into(),
2769    )
2770    .with_native_code(native_code)
2771    .with_poisoned(poisoned)
2772}
2773
2774#[cfg(target_os = "linux")]
2775fn linux_ready_batch_failure(
2776    operation: SessionOperation,
2777    state: SessionState,
2778    failure: crate::backend::linux_vnext::spawn::LinuxPublicReadyFailure,
2779) -> SessionFailure {
2780    let native_code = linux_public_native_code(failure.error);
2781    let poisoned = state == SessionState::Poisoned;
2782    SessionFailure::new(
2783        operation,
2784        if failure.transaction_open_on_failure {
2785            SessionTransactionState::TransactionOpen
2786        } else if poisoned {
2787            SessionTransactionState::Poisoned
2788        } else {
2789            SessionTransactionState::Ready
2790        },
2791        failure.error.into(),
2792    )
2793    .with_native_code(native_code)
2794    .with_poisoned(poisoned)
2795}
2796
2797#[cfg(target_os = "linux")]
2798const fn linux_public_native_code(
2799    error: crate::backend::linux_vnext::spawn::LinuxPublicSessionError,
2800) -> Option<i32> {
2801    match error {
2802        crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Native(code) => code,
2803        crate::backend::linux_vnext::spawn::LinuxPublicSessionError::ActivationFailed(code) => code,
2804        _ => None,
2805    }
2806}
2807
2808#[cfg(target_os = "linux")]
2809impl From<crate::backend::linux_vnext::spawn::LinuxPublicSessionError> for SessionError {
2810    fn from(error: crate::backend::linux_vnext::spawn::LinuxPublicSessionError) -> Self {
2811        match error {
2812            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::InvalidInput => {
2813                Self::InvalidInput
2814            }
2815            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::DeadlineExpired => {
2816                Self::DeadlineExpired
2817            }
2818            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::PeerExited => {
2819                Self::PeerDisconnected
2820            }
2821            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::IdentityMismatch => {
2822                Self::IdentityMismatch
2823            }
2824            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::MalformedPeer => {
2825                Self::MalformedPeer
2826            }
2827            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Ambiguous => {
2828                Self::Ambiguous
2829            }
2830            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::NegotiationFailed => {
2831                Self::NegotiationFailed
2832            }
2833            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::NativeNegotiation(
2834                error,
2835            ) => Self::NativeNegotiation(error),
2836            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Control(error) => {
2837                Self::Control(error)
2838            }
2839            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Batch(error) => {
2840                Self::Batch(error)
2841            }
2842            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::ActiveLimit => {
2843                Self::ActiveLimit
2844            }
2845            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::PeerPreparationFailed => {
2846                Self::PeerPreparationFailed
2847            }
2848            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::ActivationFailed(_) => {
2849                Self::ActivationFailed
2850            }
2851            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Poisoned => Self::Poisoned,
2852            crate::backend::linux_vnext::spawn::LinuxPublicSessionError::Native(_) => Self::Native,
2853        }
2854    }
2855}
2856
2857#[cfg(target_os = "macos")]
2858fn mac_session_failure(
2859    operation: SessionOperation,
2860    transaction_state: SessionTransactionState,
2861    error: crate::backend::macos::vnext_session::MacPublicSessionError,
2862    poisoned: bool,
2863) -> SessionFailure {
2864    SessionFailure::new(operation, transaction_state, error.into())
2865        .with_native_code(mac_public_native_code(error))
2866        .with_poisoned(poisoned)
2867}
2868
2869#[cfg(target_os = "macos")]
2870fn mac_ready_failure(
2871    operation: SessionOperation,
2872    state: SessionState,
2873    error: crate::backend::macos::vnext_session::MacPublicSessionError,
2874) -> SessionFailure {
2875    let poisoned = state == SessionState::Poisoned;
2876    mac_session_failure(
2877        operation,
2878        if poisoned {
2879            SessionTransactionState::Poisoned
2880        } else {
2881            SessionTransactionState::Ready
2882        },
2883        error,
2884        poisoned,
2885    )
2886}
2887
2888#[cfg(target_os = "macos")]
2889const fn mac_public_native_code(
2890    error: crate::backend::macos::vnext_session::MacPublicSessionError,
2891) -> Option<i32> {
2892    match error {
2893        crate::backend::macos::vnext_session::MacPublicSessionError::Native(code) => code,
2894        _ => None,
2895    }
2896}
2897
2898#[cfg(target_os = "macos")]
2899impl From<crate::backend::macos::vnext_session::MacPublicSessionError> for SessionError {
2900    fn from(error: crate::backend::macos::vnext_session::MacPublicSessionError) -> Self {
2901        use crate::backend::macos::vnext_session::MacPublicSessionError as MacError;
2902        match error {
2903            MacError::InvalidInput => Self::InvalidInput,
2904            MacError::DeadlineExpired => Self::DeadlineExpired,
2905            MacError::PeerExited => Self::PeerDisconnected,
2906            MacError::IdentityMismatch => Self::IdentityMismatch,
2907            MacError::MalformedPeer => Self::MalformedPeer,
2908            MacError::Ambiguous => Self::Ambiguous,
2909            MacError::NegotiationFailed => Self::NegotiationFailed,
2910            MacError::NativeNegotiation(error) => Self::NativeNegotiation(error),
2911            MacError::Control(error) => Self::Control(error),
2912            MacError::Batch(error) => Self::Batch(error),
2913            MacError::ActiveLimit => Self::ActiveLimit,
2914            MacError::PeerPreparationFailed => Self::PeerPreparationFailed,
2915            MacError::ActivationFailed => Self::ActivationFailed,
2916            MacError::Poisoned => Self::Poisoned,
2917            MacError::Native(_) => Self::Native,
2918        }
2919    }
2920}
2921
2922#[cfg(target_os = "windows")]
2923fn windows_session_failure(
2924    operation: SessionOperation,
2925    transaction_state: SessionTransactionState,
2926    error: crate::backend::windows::vnext_session::WindowsPublicSessionError,
2927    poisoned: bool,
2928) -> SessionFailure {
2929    let native_code = match &error {
2930        crate::backend::windows::vnext_session::WindowsPublicSessionError::Native(code) => *code,
2931        _ => None,
2932    };
2933    SessionFailure::new(operation, transaction_state, error.into())
2934        .with_native_code(native_code)
2935        .with_poisoned(poisoned)
2936}
2937
2938#[cfg(target_os = "windows")]
2939fn windows_ready_failure(
2940    operation: SessionOperation,
2941    state: SessionState,
2942    error: crate::backend::windows::vnext_session::WindowsPublicSessionError,
2943) -> SessionFailure {
2944    let poisoned = state == SessionState::Poisoned;
2945    windows_session_failure(
2946        operation,
2947        if poisoned {
2948            SessionTransactionState::Poisoned
2949        } else {
2950            SessionTransactionState::Ready
2951        },
2952        error,
2953        poisoned,
2954    )
2955}
2956
2957#[cfg(target_os = "windows")]
2958impl From<crate::backend::windows::vnext_session::WindowsPublicSessionError> for SessionError {
2959    fn from(error: crate::backend::windows::vnext_session::WindowsPublicSessionError) -> Self {
2960        use crate::backend::windows::vnext_session::WindowsPublicSessionError as WindowsError;
2961        match error {
2962            WindowsError::InvalidInput => Self::InvalidInput,
2963            WindowsError::DeadlineExpired => Self::DeadlineExpired,
2964            WindowsError::PeerExited => Self::PeerDisconnected,
2965            WindowsError::IdentityMismatch => Self::IdentityMismatch,
2966            WindowsError::MalformedPeer => Self::MalformedPeer,
2967            WindowsError::Ambiguous => Self::Ambiguous,
2968            WindowsError::NegotiationFailed => Self::NegotiationFailed,
2969            WindowsError::NativeNegotiation(error) => Self::NativeNegotiation(error),
2970            WindowsError::Control(error) => Self::Control(error),
2971            WindowsError::Batch(error) => Self::Batch(error),
2972            WindowsError::ActiveLimit => Self::ActiveLimit,
2973            WindowsError::PeerPreparationFailed => Self::PeerPreparationFailed,
2974            WindowsError::ActivationFailed => Self::ActivationFailed,
2975            WindowsError::Poisoned => Self::Poisoned,
2976            WindowsError::Native(_) => Self::Native,
2977        }
2978    }
2979}
2980
2981const _: () = assert!(cfg!(target_has_atomic = "32"));
2982const _: () = assert!(cfg!(target_has_atomic = "64"));
2983
2984#[cfg(test)]
2985#[path = "session_test.rs"]
2986mod tests;