use std::
{
path::PathBuf,
net::SocketAddr,
time::{ Instant, Duration },
collections::HashMap,
sync::{ Arc, Mutex as MutexSync },
};
use tokio::
{
sync::Mutex,
net::tcp::OwnedWriteHalf,
task::AbortHandle,
};
use zeroize::Zeroizing;
use crate::
{
config,
role::Role,
consts::SharedKeys,
};
#[derive(Clone)]
pub struct AvailableFile {
pub hash: [u8; 32], pub path: PathBuf, pub filename: String, pub size: u64, pub key: Zeroizing<Vec<i64>>,
pub nonce: Vec<i64>,
}
#[derive(Clone)]
pub struct Attach {
pub stream: Arc<Mutex<OwnedWriteHalf>>, pub target_id: usize, pub token: [u8; 32], }
pub enum ConnectionType {
FileUpload
{
uid: u64,
},
FileDownload
{
uid: u64,
file: AvailableFile,
},
Screen,
Attach
{
id: usize,
},
}
#[derive(Clone)]
pub enum Connection {
Authenticated
{
write_stream: Arc<Mutex<OwnedWriteHalf>>, task: AbortHandle, file_streams: Arc<MutexSync<HashMap<u64, AbortHandle>>>, screen_stream: Option<AbortHandle>, peer_addr: SocketAddr, username: String, role: Role, id: usize, keys: SharedKeys, attached_screen: Option<Attach>, last_activity: Instant, last_key_exchange: Instant, spam_violations: usize, channel: Option<String>, seq: usize, server_seq: usize, alive: bool, muted: bool, },
NonAuthenticated
{
write_stream: Arc<Mutex<OwnedWriteHalf>>, task: AbortHandle, peer_addr: SocketAddr, username: Option<String>, keys: Option<SharedKeys>, obfuscation_key: [u8; 32], last_activity: Instant, seq: usize, connect: Instant, },
}
impl Connection
{
pub fn write_stream(&self) -> &Arc<Mutex<OwnedWriteHalf>>
{
match self
{
Self::Authenticated { write_stream, .. } => write_stream,
Self::NonAuthenticated { write_stream, .. } => write_stream,
}
}
pub fn task(&self) -> &AbortHandle
{
match self
{
Self::Authenticated { task, .. } => task,
Self::NonAuthenticated { task, .. } => task,
}
}
pub fn file_streams(&self) -> Option<&Arc<MutexSync<HashMap<u64, AbortHandle>>>>
{
match self
{
Self::Authenticated { file_streams, .. } => Some(file_streams),
Self::NonAuthenticated { .. } => None,
}
}
pub fn peer_addr(&self) -> &SocketAddr
{
match self
{
Self::Authenticated { peer_addr, .. } => peer_addr,
Self::NonAuthenticated { peer_addr, .. } => peer_addr,
}
}
pub fn username(&self) -> Option<&String>
{
match self
{
Self::Authenticated { username, .. } => Some(username),
Self::NonAuthenticated { username, .. } => username.as_ref(),
}
}
pub(super) fn username_mut(&mut self) -> &mut Option<String>
{
match self
{
Self::Authenticated { .. } => panic!("Do not use username_mut() on Authenticated client"),
Self::NonAuthenticated { username, .. } => username,
}
}
pub fn role(&self) -> Option<&Role>
{
match self
{
Self::Authenticated { role, .. } => Some(role),
Self::NonAuthenticated { .. } => None,
}
}
pub fn id(&self) -> Option<&usize>
{
match self
{
Self::Authenticated { id, .. } => Some(id),
Self::NonAuthenticated { .. } => None,
}
}
pub fn keys(&self) -> Option<&SharedKeys>
{
match self
{
Self::Authenticated { keys, .. } => Some(keys),
Self::NonAuthenticated { keys, .. } => keys.as_ref(),
}
}
pub fn obfuscation_key(&self) -> Option<&[u8; 32]>
{
match self
{
Self::Authenticated { .. } => None,
Self::NonAuthenticated { obfuscation_key, .. } => Some(obfuscation_key),
}
}
pub fn last_activity(&self) -> &Instant
{
match self
{
Self::Authenticated { last_activity, .. } => last_activity,
Self::NonAuthenticated { last_activity, .. } => last_activity,
}
}
pub fn last_activity_mut(&mut self) -> &mut Instant
{
match self
{
Self::Authenticated { last_activity, .. } => last_activity,
Self::NonAuthenticated { last_activity, .. } => last_activity,
}
}
pub fn last_key_exchange(&self) -> Option<&Instant>
{
match self
{
Self::Authenticated { last_key_exchange, .. } => Some(last_key_exchange),
Self::NonAuthenticated { .. } => None,
}
}
pub fn spam_violations(&self) -> Option<&usize>
{
match self
{
Self::Authenticated { spam_violations, .. } => Some(spam_violations),
Self::NonAuthenticated { .. } => None,
}
}
pub fn spam_violations_mut(&mut self) -> Option<&mut usize>
{
match self
{
Self::Authenticated { spam_violations, .. } => Some(spam_violations),
Self::NonAuthenticated { .. } => None,
}
}
pub fn channel(&self) -> &Option<String>
{
match self
{
Self::Authenticated { channel, .. } => channel,
Self::NonAuthenticated { .. } => &None,
}
}
pub fn seq(&self) -> &usize
{
match self
{
Self::Authenticated { seq, .. } => seq,
Self::NonAuthenticated { seq, .. } => seq,
}
}
pub fn seq_mut(&mut self) -> &mut usize
{
match self
{
Self::Authenticated { seq, .. } => seq,
Self::NonAuthenticated { seq, .. } => seq,
}
}
pub fn server_seq(&self) -> Option<&usize>
{
match self
{
Self::Authenticated { server_seq, .. } => Some(server_seq),
Self::NonAuthenticated { .. } => None,
}
}
pub fn server_seq_mut(&mut self) -> Option<&mut usize>
{
match self
{
Self::Authenticated { server_seq, .. } => Some(server_seq),
Self::NonAuthenticated { .. } => None,
}
}
pub(super) fn is_inactive(&self, now: Option<Instant>) -> bool
{
match self
{
Self::Authenticated { last_activity, .. } =>
{
now.unwrap_or_else(Instant::now).duration_since(*last_activity) >
Duration::from_secs(config::read_config::<u64>("communication_time"))
},
Self::NonAuthenticated { connect, .. } =>
{
now.unwrap_or_else(Instant::now).duration_since(*connect) >
Duration::from_secs(config::read_config::<u64>("max_auth_time"))
},
}
}
pub fn is_authenticated(&self) -> bool
{
match self
{
Self::Authenticated { .. } => true,
Self::NonAuthenticated { .. } => false,
}
}
pub fn set_alive(&mut self, val: bool)
{
match self
{
Self::Authenticated { alive, .. } => *alive = val,
_ => {}
}
}
pub fn is_alive(&self) -> &bool
{
match self
{
Self::Authenticated { alive, .. } => alive,
Self::NonAuthenticated { .. } => &false,
}
}
pub fn add_file_stream(&self, uid: u64, task: AbortHandle)
{
if let Self::Authenticated { file_streams, .. } = self
{
file_streams.lock().unwrap().insert(uid, task);
}
}
pub fn remove_file_stream(&self, uid: u64)
{
if let Self::Authenticated { file_streams, .. } = self
{
if let Some(task) = file_streams.lock().unwrap().remove(&uid)
{
task.abort(); }
}
}
pub fn screen_stream(&self) -> &Option<AbortHandle>
{
match self
{
Self::Authenticated { screen_stream, .. } => screen_stream,
Self::NonAuthenticated { .. } => &None,
}
}
pub fn attached_screen(&self) -> &Option<Attach>
{
match self
{
Self::Authenticated { attached_screen, .. } => attached_screen,
Self::NonAuthenticated { .. } => &None,
}
}
pub fn attach_screen(&mut self, target_id: usize, stream: Arc<Mutex<OwnedWriteHalf>>, token: [u8; 32])
{
match self
{
Self::Authenticated { attached_screen, .. } => *attached_screen = Some(Attach
{
target_id,
stream,
token,
}),
_ => {},
}
}
pub fn deattach_screen(&mut self)
{
match self
{
Self::Authenticated { attached_screen, .. } =>
{
*attached_screen = None;
log::info!("Stop screen attach: {}", self.peer_addr());
},
_ => {},
}
}
pub fn set_screen_stream(&mut self, task: AbortHandle)
{
self.remove_screen_stream();
if let Self::Authenticated { screen_stream, .. } = self
{
*screen_stream = Some(task);
}
}
pub fn take_screen_stream(&mut self) -> Option<(usize, AbortHandle)>
{
if let Self::Authenticated { screen_stream, peer_addr, id, .. } = self
{
if let Some(old_task) = screen_stream.take()
{
log::info!("Stop screenshare: {}", peer_addr);
return Some((*id, old_task));
}
}
None
}
pub fn remove_screen_stream(&mut self) -> Option<usize>
{
self.take_screen_stream().map(|(id, old_task)|
{
old_task.abort();
id
})
}
pub fn toggle_mute(&mut self)
{
if let Self::Authenticated { muted, .. } = self
{
*muted = !*muted;
}
}
pub fn set_role(&mut self, new_role: Role)
{
if let Self::Authenticated { role, .. } = self
{
*role = new_role;
}
}
pub fn muted(&self) -> &bool
{
match self
{
Self::Authenticated { muted, .. } => muted,
Self::NonAuthenticated { .. } => &false,
}
}
}