1use crate::{cli::SubCommand, command::CommandError, context::ContextCache, device::Device};
5use argh::FromArgs;
6use std::{cell::RefCell, rc::Rc};
7use strum::{Display, EnumString};
8use tabled::Tabled;
9use tpm2_protocol::data::TpmSe;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Display, EnumString)]
12#[strum(serialize_all = "kebab-case")]
13pub enum SessionType {
14 Hmac,
15 Policy,
16 Trial,
17}
18
19impl From<TpmSe> for SessionType {
20 fn from(val: TpmSe) -> Self {
21 match val {
22 TpmSe::Hmac => Self::Hmac,
23 TpmSe::Policy => Self::Policy,
24 TpmSe::Trial => Self::Trial,
25 }
26 }
27}
28
29#[derive(Tabled)]
30struct SessionRow {
31 #[tabled(rename = "HANDLE")]
32 handle: String,
33 #[tabled(rename = "DETAILS")]
34 details: String,
35}
36
37#[derive(FromArgs, Debug)]
39#[argh(
40 subcommand,
41 name = "session",
42 note = "Lists cached authorization sessions."
43)]
44pub struct Session {
45 #[argh(option, long = "type")]
47 pub type_filter: Option<SessionType>,
48}
49
50impl SubCommand for Session {
51 fn run(
52 &self,
53 _device: Option<Rc<RefCell<Device>>>,
54 context: &mut ContextCache,
55 plain: bool,
56 ) -> Result<(), CommandError> {
57 let mut results: Vec<(u32, SessionType)> = Vec::new();
58
59 for (_, session) in &context.session_map {
60 let handle = session.context.saved_handle.0;
61 results.push((handle, session.session_type.into()));
62 }
63
64 if let Some(filter_type) = self.type_filter {
65 results.retain(|(_, session_type)| *session_type == filter_type);
66 }
67
68 results.sort_unstable();
69
70 let rows: Vec<SessionRow> = results
71 .into_iter()
72 .map(|(handle, session_type)| SessionRow {
73 handle: format!("session://{handle:08x}"),
74 details: session_type.to_string(),
75 })
76 .collect();
77
78 super::print_table(&mut context.writer, rows, plain)?;
79
80 Ok(())
81 }
82}