snap_dataplane/session/state/
dto.rs

1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//! Data transfer objects (DTOs) for SNAP data plane session state.
15
16use std::{
17    collections::BTreeMap,
18    str::FromStr,
19    time::{Duration, UNIX_EPOCH},
20};
21
22use scion_sdk_common_types::ed25519::Ed25519SigningKeyPem;
23use serde::{Deserialize, Serialize};
24use snap_tokens::Pssid;
25use utoipa::ToSchema;
26
27use crate::{
28    session::state::{Session, SessionId, SessionManagerState, SessionTokenIssuerState},
29    state::DataPlaneId,
30};
31
32/// The session manager state.
33#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
34pub struct SessionManagerStateDto {
35    /// The maximum duration of a session.
36    pub session_duration: Duration,
37    /// List of existing sessions.
38    pub sessions: Vec<SessionDto>,
39}
40
41impl From<&SessionManagerState> for SessionManagerStateDto {
42    fn from(value: &SessionManagerState) -> Self {
43        Self {
44            session_duration: value.session_duration,
45            sessions: value
46                .sessions
47                .iter()
48                .map(|(session_id, session)| {
49                    SessionDto {
50                        session_id: SessionIdDto {
51                            pssid: session_id.pssid.0.to_string(),
52                            data_plane_id: session_id.data_plane_id,
53                        },
54                        expiry: session.expiry.duration_since(UNIX_EPOCH).unwrap().as_secs(),
55                    }
56                })
57                .collect(),
58        }
59    }
60}
61
62impl TryFrom<SessionManagerStateDto> for SessionManagerState {
63    type Error = std::io::Error;
64
65    fn try_from(value: SessionManagerStateDto) -> Result<Self, Self::Error> {
66        let sessions: BTreeMap<SessionId, Session> = value
67            .sessions
68            .into_iter()
69            .map(|session| {
70                Pssid::from_str(&session.session_id.pssid).map(|pssid| {
71                    let session_id = SessionId::new(pssid, session.session_id.data_plane_id);
72                    let expiry = UNIX_EPOCH + Duration::from_secs(session.expiry);
73                    (session_id, Session::new(expiry))
74                })
75            })
76            .collect::<Result<_, _>>()?;
77
78        Ok(SessionManagerState {
79            session_duration: value.session_duration,
80            sessions,
81        })
82    }
83}
84
85/// Data plane session.
86#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
87pub struct SessionDto {
88    /// The ID of the session.
89    pub session_id: SessionIdDto,
90    /// The expiry time of the session represented as a Unix timestamp.
91    pub expiry: u64,
92}
93
94/// Session ID.
95#[derive(Debug, Ord, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Clone, ToSchema)]
96pub struct SessionIdDto {
97    /// The pseudo SCION subscriber identity (PSSID).
98    pub pssid: String,
99    /// The ID of the data plane.
100    pub data_plane_id: DataPlaneId,
101}
102
103/// Session token issuer state.
104#[derive(Debug, Serialize, Deserialize, ToSchema, Clone)]
105pub struct SessionTokenIssuerStateDto {
106    /// The encoding key (PEM format) used to issue session tokens.
107    pub key: String,
108}
109impl From<&SessionTokenIssuerState> for SessionTokenIssuerStateDto {
110    fn from(value: &SessionTokenIssuerState) -> Self {
111        Self {
112            key: value.key.warning_to_private_key_pem(),
113        }
114    }
115}
116
117impl TryFrom<SessionTokenIssuerStateDto> for SessionTokenIssuerState {
118    type Error = std::io::Error;
119
120    fn try_from(value: SessionTokenIssuerStateDto) -> Result<Self, Self::Error> {
121        let key = Ed25519SigningKeyPem::from_str(&value.key)
122            .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
123        Ok(SessionTokenIssuerState { key })
124    }
125}