Skip to content

PdS2425-C2/G46

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

143 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ruggine - App di Chat Testuale in Rust

Ruggine è un'applicazione di messaggistica instantanea multipiattaforma scritta in Rust, focus su performance e monitoraggio delle risorse.

Introduzione

Questo documento presenta il Progetto 2.1 – Ruggine, un'applicazione di chat testuale, sviluppata per il corso di Programmazione di sistema. Il progetto consiste nella realizzazione un sistema di tipo client/server in grado di gestire lo scambio di messaggi testuali tra utenti.

Partecipanti al gruppo

  • Simone Columbaro – s343584
  • Alex Drapant – s349529
  • Lorenzo Brasolin – s349526
  • Elia Francesco Vigè – s339126

La documentazione prodotta è articolata in più sezioni, ciascuna finalizzata a descrivere il progetto da punti di vista differenti: dalla progettazione all'utilizzo.

Indice

Manuale Utente

1. Introduzione

L'applicazione consente di creare gruppi di utenti per la condivisione di messaggi. L'accesso alla chat è effettuato all'avvio del programma, tramite una richiesta di login al server: è necessario fornire username e password di un account già presente nel database (pre-popolato). L'ingresso nei gruppi, invece, avviene esclusivamente tramite invito. L'applicazione è progettata per funzionare sui principali sistemi operativi, Windows, macOS e Linux. Nella parte finale di questo documento sono riportate le prestazioni del sistema, incluse le misurazioni del tempo di CPU e della dimensione dell’eseguibile. Inoltre, il sistema genera file di log contenenti i dettagli sull’utilizzo della CPU, registrati ogni 2 minuti.

1.1 Obiettivi del progetto

Il sistema è stato progettato per soddisfare i seguenti requisiti

  • Gestione di conversazioni singole (Direct Message) e di gruppo.
  • Comunicazione in tempo reale tramite protocollo WebSocket.
  • Peristenza dello storico messaggi garantita da un database relazionale.
  • Compatibilità cross-platform (testato su Windows10/11 e macOS 12+)
  • Monitoraggio attivo delle risorse (CPU/RAM) con logging periodico

1.2 Requisiti tecnici

Sistema operativo

  • Windows 10 o successivo.
  • macOS 12 o successivo.

Connessione di rete

  • Rete Wi-Fi generica.

Requisiti software

  • Rust : ≥ 1.80+.
  • Visual Studio Build Tools (C++ workload) su Windows mentre Xcode Command Line Tools su MacOS.

2. Installazione

In questa sezione vedremo come installare e far partire correttamente l'applicazione

2.1 Download e setup

  • Scaricare l'applicazione dalla Repository ufficiale
  • Aprire il progetto in Visual Studio Code o in qualunque altra IDE.
  • Il progetto è suddiviso in due cartelle principali:
    • client/ → cartella contenente Client
    • server/ → cartella contenente la logica di gestione delle risorse

2.2 Avvio e Compilazione

Per ottenere le massime prestazioni e un eseguibile di dimensioni ridotte, si raccomanda la compilazione in modalità release

  1. Avvio server: aprire il terminale e usare i seguenti comandi in bash:
cd server
cargo run --release
  1. Avvio client: aprire un nuovo terminale per ogni client che si desidera connettere e usare i seguenti comandi in bash:
cd client
cargo run 

Nota: Al primo avvio, Cargo scaricherà e compilerà automaticamente tutte le dipendenze.

  1. Inserire una delle seguenti credenziali:
  • username: simone, password: password
  • username: alex, password: password
  • username: lorenzo, password: password
  • username: elia, password: password

Manuale del progettista

1. Struttura del Progetto

Il progetto è organizzato come un Rust Workspace suddiviso in quattro crate principali:

  • protocol/
  • server/
  • client/
  • hw-monitoring/

2. Architettura del sistema

Il sistema adotta un'architettura Client-Server asincrona basata su scambio di messaggi JSON su WebSocket.

+-----------------------+                    +--------------------------+
|        CLIENT         |                    |          SERVER          |
|                       |                    |                          |
|  +-----------------+  |                    |  +--------------------+  |
|  |   Interfaccia   |  |   Connessione      |  | Gestore Connessioni|  |
|  |     Grafica     |  |<==================>|  | (Ricezione Dati)   |  |
|  +--------+--------+  |    WebSocket       |  +---------+----------+  |
|           ^           |                    |            ^             |
|           |           |                    |            |             |
|  +--------v--------+  |                    |  +---------v----------+  |
|  | Modulo di Rete  |  |                    |  | Logica Applicativa |  |
|  | (Comunicazione) |  |                    |  | (Smistamento Msg)  |  |
|  +-----------------+  |                    |  +---------+----------+  |
|                       |                    |            ^             |
+-----------------------+                    |            |             |
                                             |  +---------v----------+  |
                                             |  |   Gestore Dati     |  |
                                             |  |   (Salvataggio)    |  |
                                             |  +---------+----------+  |
                                             |            |             |
                                             +------------+-------------+
                                                          |
                                                  +-------v------+
                                                  |   Archivio   |
                                                  |   (Su DB)    |
                                                  +--------------+

3. Struttura dei componenti

3.1 Frontend (client/)

Il frontend è un'applicazione desktop sviluppata interamente in Rust utilizzando egui, un framework GUI nativo e immediato che offre un'esperienza utente fluida e reattiva.

3.1.1 Architettura Frontend

L'applicazione client è strutturata attorno a uno state centralizzato (AppState) che gestisce tutti i dati dell'interfaccia:

  • Autenticazione: Stato di login gestito tramite enum AuthState
  • Messaggistica: HashMap separate per messaggi diretti (messages) e di gruppo (group_messages)
  • Gruppi: Lista dei gruppi con membri e metadati (groups)
  • Gestione UI: Stato dell'interfaccia (selected_chat,input_message, etc)

3.1.2 Funzionalità principali

3.1.3 Sistema di autenticazione

  • Schermata login con username e password
  • Validazione input e gestione errori
  • Transizione automatica all'interfaccia principale dopo il login

3.1.4 Interfaccia chat

L'interfaccia è divisa in tre pannelli:

  1. Pannello Laterale (Sidebar):
    • Lista utenti connessi per chat dirette
    • Lista dei gruppi con nome e conteggio membri
    • Pulsante per la creazione di nuovi gruppi
  2. Pannello centrale:
    • Header con informazioni sulla chat (nome utente/gruppo, lista membri)
    • Area messaggi con scroll
    • Campo di input per nuovi messaggi
  3. Modale per creazione gruppo:
    • Selezione multipla degli utenti da invitare
    • Campo per il nome del gruppo
    • Conferma/annullamento creazione gruppo

3.1.5 Gestione messaggi

  • Caricamento Lazy: i messaggi vengono richiesti solo quando l'utente apre una chat
  • Cache locale: i messaggi caricati vengono salvati in memoria per evitare richieste duplicate
  • Separazione logica: HashMap separate per messaggi diretti e di gruppo
  • Timestamp: visualizzazione dell'ora di invio per ogni messaggio (facendo hover sul messaggio)

3.1.6 Gestione gruppi

  • Creazione: selezione degli utenti e assegnazioni di un nome
  • Visualizzazione membri: Header espandibile
  • Colori utente: ogni membro riceve un colore distintivo generato deterministicamente
  • Uscita dal gruppo: Pulsante dedicato per uscire dal gruppo, con aggiornamento real-time agli altri membri

3.1.7 Pattern di design

Per riassumere, questi sono i pattern di design adoperati per la gestione del client:

  • State management: Stato centralizzato con lock (Mutex) per thread-safety
  • Separation of concerns: Funzioni separate per rendering dei diversi componenti UI
  • Event-Driven: Reazioni agli eventi utente e ai messaggi del server

3.2 Backend (server/)

Il backend è costruito sopra il runtime asincrono Tokio. -main.rs: Punto di ingresso. Inizializza il thread di monitoraggio risorse, apre il pool di connessione al DB e si mette in ascolto sulla porta TCP configurata (default 3001). Per ogni nuova connessione, spawna un task tokio. -server.rs: Gestisce il ciclo di vita della connessione. Utilizza canali mpsc per gestire la concorrenza tra la ricezione di messaggi dal socket e l'invio di messaggi verso il client.

3.2.1 Contenuto delle cartelle

src/ - I componenti principali

Questa cartella contiene il punto di ingresso dell'applicazione e la logica di gestione delle connessioni e degli eventi.

  • main.rs: È il punto di ingresso (Entry Point) del backend e gestisce l'infrastruttura di rete. Le sue responsabilità principali sono:

    • Inizializzazione: Configura il runtime asincrono tokio, apre la connessione al database (DbPool) e avvia il thread per il monitoraggio hardware.
    • Gestione TCP/WebSocket: Si mette in ascolto sulla porta configurata e accetta le connessioni in ingresso, eseguendo l'handshake WebSocket tramite tokio_tungstenite.
    • Task Spawning: Per ogni client connesso, genera ("spawna") un task asincrono isolato. Questo task gestisce due loop concorrenti: uno per la lettura dei messaggi dal socket e uno per la scrittura verso il client, utilizzando canali mpsc per la comunicazione interna.
    • Routing Iniziale: Deserializza i messaggi JSON in ingresso e delega la loro elaborazione alla logica di business definita in server.rs.
  • server.rs: Contiene il cuore della "Business Logic" e la gestione dello stato condiviso. Le sue componenti chiave sono:

    • ServerState: Una struttura dati (protetta da Arc<Mutex<...>> nel main) che mantiene in memoria la mappa dei client connessi, le sessioni utente attive (utenti loggati) e la cache dei gruppi.
    • process_command: Funzione dispatcher che riceve i comandi inviati dal client (enum ClientToServer) e chiama il gestore appropriato (es. login, invio messaggio, creazione gruppo).
    • Gestori di Eventi: Metodi specifici (come handle_login, handle_dm, handle_create_group) che coordinano l'interazione tra la memoria volatile (stato delle connessioni) e la memoria persistente (chiamate al modulo DB).

db/ Cartella contenente Database e API per interagire con il Database

Questa cartella astrae la logica di persistenza dei dati. Contiene i moduli che espongono funzioni Rust per eseguire query SQL sul database SQLite, suddivisi per entità logica:

  • client.rs: Gestisce le operazioni relative agli account utente:

    • Autenticazione: verifica della validità della coppia username/password (con gestione dell'hashing).
    • Risoluzione identità: conversione da Username a UUID e viceversa, necessaria per mappare i messaggi in arrivo (che contengono ID) ai nomi visualizzati nella GUI.
    • Recupero dati: ottenimento della lista completa dei client o di singoli record utente.
  • groups.rs: Gestisce la struttura e la composizione dei gruppi. Include funzioni per:

    • Creazione: inserimento di nuovi gruppi e associazione iniziale dei membri.
    • Gestione membri: aggiunta massiva di utenti a un gruppo e rimozione (leave) di un utente specifico.
    • Query: recupero di tutti i gruppi a cui appartiene un utente e, viceversa, di tutti i membri di un gruppo specifico.
  • messages.rs: Si occupa dello storico delle conversazioni. Fornisce le API per:

    • Persistenza: salvataggio di nuovi messaggi (sia diretti che di gruppo) con timestamp.
    • Recupero Cronologia DM: caricamento dei messaggi scambiati tra due specifici utenti, ordinati temporalmente.
    • Recupero Cronologia Gruppi: caricamento di tutti i messaggi associati a un group_id.
  • mod.rs: È il punto di ingresso del modulo database. Si occupa di:

    • Inizializzare la connessione (Connection Pool) verso il file database1.sqlite.
    • Esporre pubblicamente i sottomoduli (clients, groups, messages) al resto dell'applicazione server.

3.2.2 File database1.sqlite

Questo file contiene il database ed è suddiviso nel seguente modo:

  • La struttura della tabella "clients" include le colonne : id_client, nome_utente, password, salt

3.3 Protocollo di Comunicazione (protocol/)

La comunicazione avviene tramite serializzazione JSON(crate serde_json). Sono definite due enum principali nel crate condiviso protocol:

  • ClientToServer: Comandi inviati dal client (es. Login, Dm,CreateGroup).
  • ServerToClient: Risposte o eventi push dal server (es Welcome,Dm,Join,LoginSuccess).

3.4 Monitoraggio risorse hardware

Struttura:

  • Crate separato hw-monitoring con dipendenze: sysinfo, chrono, tokio, fs2
  • Struct CpuMonitor che traccia nome processo, path log, e System di sysinfo

Funzionamento:

  • Inizializzazione (CpuMonitor::new): riceve il nome del processo a cui aggiunge il PID, definisce dove scrivere il log e crea l'oggetto che leggerà dati quali CPU e memoria dal sistema operativo, racchiuso in Arc < Mutex > per un async sicuro
  • Monitoraggio (start_monitoring): funzione async che ogni 2 minuti fa refresh dei processi, legge il PID corrente che usa per ottenere la CPU usage e la memoria (fisica in RAM) del processo con quel PID
  • Scrittura (write_to_log): crea la direcotry logs/ se non esiste e apre il file cpu_usage-log in modalità append. Utilizza un lock esclusivo (fs2::FileExt) per evitare race conditions, di modo che più processi possano scrive sullo stesso file

Integrazione in server e client:

  • Dopo l'avvio del processo principale nel main.rs viene spawnato un task asincrono separato che monitora le risorse in background, questo per ogni nuova istanza di server o client avviata

4. Analisi e valutazione

Sono stati effettuati test di monitorggio utilizzando il modulo hw-monitoringintegrato. Configurazione di test [AppleM2], Build --release.

Stato del Client Utilizzo CPU Medio Utilizzo Memoria (RAM)
Idle (Background) < 1.0% ~60 MB
Ricezione Messaggi 4% - 6.0% ~65 MB
Stato del Server Utilizzo CPU Medio Utilizzo Memoria (RAM)
Idle (Background) < 1.0% ~5 MB
Ricezione Messaggi < 1.0 % ~5 MB

5. Interfaccia grafica

Schermata di login

LoginPage

Ingresso nell'app

FirstPage

Esempio di chat diretta

Esempio di chat di gruppo

GroupChat

6. Eseguibile Client

L'uso di cargo build --releaserimuove i simboli di debug e applica ottimizzazioni LTO (Link Time Optimization), riducendo drasticamente la dimensione.

Componente Windows (.exe) macOS (Binary)
Client (GUI) ~5.7 MB ~6,2 MB
Server (CLI) ~4.2 MB ~4,7 MB

About

Ruggine

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages