ziti_sdk/session/
manager.rs1use super::{api_session, ApiSession, NetworkSession};
6use crate::error::{ZitiError, ZitiResult};
7use crate::identity::IdentityManager;
8use crate::transport::http::controller_client;
9use serde::Deserialize;
10use std::sync::Arc;
11use std::time::Duration;
12use tokio::sync::RwLock;
13
14#[derive(Debug, Deserialize)]
16struct CreateSessionResponse {
17 data: SessionData,
18}
19
20#[derive(Debug, Deserialize)]
21struct SessionData {
22 id: String,
23}
24
25#[derive(Clone)]
27pub struct SessionManager {
28 identity_manager: Arc<IdentityManager>,
29 current_api_session: Arc<RwLock<Option<ApiSession>>>,
30}
31
32impl SessionManager {
33 pub fn new(identity_manager: IdentityManager) -> Self {
35 Self {
36 identity_manager: Arc::new(identity_manager),
37 current_api_session: Arc::new(RwLock::new(None)),
38 }
39 }
40
41 pub async fn get_api_session(&self) -> ZitiResult<ApiSession> {
66 {
68 let session_guard = self.current_api_session.read().await;
69 if let Some(ref session) = *session_guard
70 && !session.is_expired()
71 {
72 return Ok(session.clone());
73 }
74 }
75
76 let new_session = api_session::authenticate(&self.identity_manager).await?;
78
79 {
81 let mut session_guard = self.current_api_session.write().await;
82 *session_guard = Some(new_session.clone());
83 }
84
85 Ok(new_session)
86 }
87
88 pub async fn get_network_session(&self, service_id: &str) -> ZitiResult<NetworkSession> {
101 let api_session = self.get_api_session().await?;
103
104 let client = controller_client(&self.identity_manager, Duration::from_secs(30)).await?;
105
106 let sessions_url = format!(
107 "{}/sessions",
108 self.identity_manager.zt_api().trim_end_matches('/')
109 );
110
111 let request_body = serde_json::json!({
112 "serviceId": service_id,
113 "type": "Dial",
114 });
115
116 let response = client
117 .post(&sessions_url)
118 .header("Content-Type", "application/json")
119 .header("zt-session", &api_session.token)
120 .json(&request_body)
121 .send()
122 .await
123 .map_err(|e| {
124 ZitiError::ConnectionFailed(format!("Failed to create network session: {}", e))
125 })?;
126
127 if !response.status().is_success() {
128 let status = response.status();
129 let error_text = response
130 .text()
131 .await
132 .unwrap_or_else(|_| "Unknown error".to_string());
133 return Err(ZitiError::ProtocolError {
134 message: format!(
135 "Network session request failed with status {}: {}",
136 status, error_text
137 ),
138 });
139 }
140
141 let session_response: CreateSessionResponse =
142 response.json().await.map_err(|e| ZitiError::ProtocolError {
143 message: format!("Failed to parse network session response: {}", e),
144 })?;
145
146 Ok(NetworkSession::new(
147 session_response.data.id,
148 service_id.to_string(),
149 ))
150 }
151
152 pub async fn clear_api_session(&self) {
157 let mut session_guard = self.current_api_session.write().await;
158 *session_guard = None;
159 }
160
161 pub async fn has_valid_api_session(&self) -> bool {
167 let session_guard = self.current_api_session.read().await;
168 if let Some(ref session) = *session_guard {
169 !session.is_expired()
170 } else {
171 false
172 }
173 }
174
175 pub fn identity_manager(&self) -> &IdentityManager {
177 &self.identity_manager
178 }
179}
180
181#[cfg(test)]
182mod tests {
183 }