init
This commit is contained in:
162
src/domain/client.rs
Normal file
162
src/domain/client.rs
Normal file
@@ -0,0 +1,162 @@
|
||||
//! 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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user