162 lines
4.4 KiB
Rust
162 lines
4.4 KiB
Rust
//! Gestion des clients pour les connexions UDP
|
|
//!
|
|
//! Ce module fournit les structures et méthodes pour gérer les clients
|
|
//! connectés au serveur UDP, incluant leur tracking et leurs modifications.
|
|
|
|
use std::net::SocketAddr;
|
|
use std::sync::Arc;
|
|
use dashmap::DashMap;
|
|
use tokio::time::Instant;
|
|
use uuid::Uuid;
|
|
use std::hash::{Hash, Hasher};
|
|
use std::time::Duration;
|
|
|
|
/// Représente un client connecté au serveur UDP
|
|
///
|
|
/// Chaque client est identifié par un UUID unique et contient
|
|
/// son adresse réseau ainsi que l'heure de sa dernière activité.
|
|
#[derive(Debug)]
|
|
pub struct Client {
|
|
id: Uuid,
|
|
address: SocketAddr,
|
|
last_seen: Instant,
|
|
}
|
|
|
|
/// Gestionnaire threadsafe pour les clients connectés
|
|
///
|
|
/// Utilise `DashMap` pour permettre un accès concurrent sécurisé
|
|
/// aux clients depuis plusieurs threads.
|
|
#[derive(Clone)]
|
|
pub struct ClientManager {
|
|
clients: Arc<DashMap<SocketAddr, Client>>,
|
|
}
|
|
|
|
impl Client {
|
|
/// Crée un nouveau client avec un UUID généré automatiquement
|
|
pub fn new(address: SocketAddr) -> Self {
|
|
let id = Uuid::new_v4();
|
|
Self {
|
|
id,
|
|
address,
|
|
last_seen: Instant::now(),
|
|
}
|
|
}
|
|
|
|
/// Retourne le UUID unique du client
|
|
pub fn id(&self) -> Uuid {
|
|
self.id
|
|
}
|
|
|
|
/// Retourne l'adresse socket du client
|
|
pub fn address(&self) -> SocketAddr {
|
|
self.address
|
|
}
|
|
|
|
/// Retourne l'instant de la dernière activité du client
|
|
pub fn last_seen(&self) -> Instant {
|
|
self.last_seen
|
|
}
|
|
|
|
/// Met à jour l'heure de dernière activité du client à maintenant
|
|
pub fn update_last_seen(&mut self) {
|
|
self.last_seen = Instant::now();
|
|
}
|
|
}
|
|
|
|
impl Hash for Client {
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
self.id.hash(state);
|
|
}
|
|
}
|
|
|
|
impl PartialEq for Client {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.id == other.id
|
|
}
|
|
}
|
|
|
|
impl Eq for Client {}
|
|
|
|
impl ClientManager {
|
|
/// Crée un nouveau gestionnaire de clients vide
|
|
pub fn new() -> Self {
|
|
Self {
|
|
clients: Arc::new(DashMap::new()),
|
|
}
|
|
}
|
|
|
|
/// Ajoute un client au gestionnaire
|
|
pub fn add(&self, client: Client) {
|
|
self.clients.insert(client.address(), client);
|
|
}
|
|
|
|
/// Supprime un client du gestionnaire
|
|
pub fn remove(&self, client: Client) {
|
|
self.clients.remove(&client.address());
|
|
}
|
|
|
|
/// Vérifie si un client existe pour une adresse donnée
|
|
pub fn client_exists(&self, address: SocketAddr) -> bool {
|
|
self.clients.contains_key(&address)
|
|
}
|
|
|
|
/// Récupère une référence vers un client par son adresse
|
|
pub fn get_client_by_address(&self, address: SocketAddr) -> Option<dashmap::mapref::one::Ref<SocketAddr, Client>> {
|
|
self.clients.get(&address)
|
|
}
|
|
|
|
/// Récupère toutes les adresses des clients connectés
|
|
pub fn get_all_adresses(&self) -> Vec<SocketAddr> {
|
|
self.clients.iter().map(|entry| *entry.key()).collect()
|
|
}
|
|
|
|
/// Met à jour l'heure de dernière activité d'un client
|
|
pub fn update_client_last_seen(&self, address: SocketAddr) {
|
|
if let Some(mut client) = self.clients.get_mut(&address) {
|
|
client.update_last_seen();
|
|
}
|
|
}
|
|
|
|
/// Supprimer les clients trop vieux
|
|
pub fn cleanup(&self, max_age: Duration) {
|
|
let now = Instant::now();
|
|
self.clients.retain(|_, client| now - client.last_seen() < max_age);
|
|
}
|
|
|
|
/// Modifie un client via une closure
|
|
///
|
|
/// # Arguments
|
|
/// * `address` - L'adresse du client à modifier
|
|
/// * `f` - La closure qui recevra une référence mutable vers le client
|
|
///
|
|
/// # Returns
|
|
/// `true` si le client a été trouvé et modifié, `false` sinon
|
|
///
|
|
/// # Examples
|
|
/// ```ignore
|
|
/// let client_manager = ClientManager::new();
|
|
/// let addr = "127.0.0.1:8080".parse().unwrap();
|
|
///
|
|
/// // Mise à jour simple
|
|
/// client_manager.modify_client(addr, |client| {
|
|
/// client.update_last_seen();
|
|
/// });
|
|
///
|
|
/// // Modifications multiples
|
|
/// let success = client_manager.modify_client(addr, |client| {
|
|
/// client.update_last_seen();
|
|
/// // autres modifications...
|
|
/// });
|
|
/// ```
|
|
pub fn modify_client<F>(&self, address: SocketAddr, f: F) -> bool
|
|
where
|
|
F: FnOnce(&mut Client),
|
|
{
|
|
if let Some(mut client) = self.clients.get_mut(&address) {
|
|
f(&mut *client);
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
} |