%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\documentclass[12pt,a4paper]{book} % o article, book, ...
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% packages...
\usepackage[utf8]{inputenc}
\usepackage[english, italian]{babel}
\usepackage[hyphens]{url}
%\usepackage{showframe}

% Per generare il file PDF aderente alle specifiche PDF/A-1b. Verificarne poi la validità.
\usepackage{colorprofiles}
\usepackage[a-2b,mathxmp]{pdfx}

\usepackage{hyperref}
\hypersetup{
    colorlinks,
    linkcolor={black!100!black},
    citecolor={blue!100!black},
    urlcolor={blue!100!black}
}

\usepackage{biblatex}
\bibliography{Biblio.bib}

\usepackage{graphicx}

\usepackage{amsmath}

\usepackage{geometry}

\usepackage{tabularx}

\usepackage{booktabs}

\usepackage{float}

\usepackage{caption}
\captionsetup[figure]{labelsep=period}

\usepackage{lipsum} % Per inserire testo a caso in attesa di realizzare i capitoli

\usepackage{xcolor}
\usepackage{listings}
\lstset{ 
    language=Python, % choose the language of the code
    basicstyle=\fontfamily{pcr}\selectfont\footnotesize\color{red},
    keywordstyle=\color{blue}\bfseries, % style for keywords
    numbers=none, % where to put the line-numbers
    numberstyle=\tiny, % the size of the fonts that are used for the line-numbers     
    %backgroundcolor=\color{darkgray},
    showspaces=false, % show spaces adding particular underscores
    showstringspaces=false, % underline spaces within strings
    showtabs=false, % show tabs within strings adding particular underscores
    frame=single, % adds a frame around the code
    tabsize=2, % sets default tabsize to 2 spaces
    %rulesepcolor=\color{gray},
    %rulecolor=\color{black},
    captionpos=b, % sets the caption-position to bottom
    breaklines=true, % sets automatic line breaking
    breakatwhitespace=false,
    stringstyle=\color{green!50!black},
    emph={StatsSetupPlugin,StatsDownloadPlugin,DefaultStatsSetupPlugin,__init__},
    emphstyle=\color{red!70!black},
}

\lstdefinelanguage{json}{
    basicstyle=\normalfont\ttfamily,
    numbers=none,
    numberstyle=\scriptsize,
    breaklines=true,
    frame=single,
    %backgroundcolor=\color{gray!10},
    showstringspaces=false,
    string=[db]{"},
    stringstyle=\color{green!50!black},
    morestring=[s][\color{black}]{\ \ "}{":},
    keywordstyle=\color{blue},
    keywords={true,false,null},
    literate=
     *{0}{{{\color{red}0}}}{1}
      {1}{{{\color{red}1}}}{1}
      {2}{{{\color{red}2}}}{1}
      {3}{{{\color{red}3}}}{1}
      {4}{{{\color{red}4}}}{1}
      {5}{{{\color{red}5}}}{1}
      {6}{{{\color{red}6}}}{1}
      {7}{{{\color{red}7}}}{1}
      {8}{{{\color{red}8}}}{1}
      {9}{{{\color{red}9}}}{1}
      {.}{{{\color{red}.}}}{1}
      {:}{{{\color{gray}{:}}}}{1}
      {,}{{{\color{gray}{,}}}}{1}
      {\{}{{{\color{gray}{\{}}}}{1}
      {\}}{{{\color{gray}{\}}}}}{1}
      {[}{{{\color{gray}{[}}}}{1}
      {]}{{{\color{gray}{]}}}}{1},
}

\lstdefinelanguage{JavaScript}{
  keywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, if, in, while, do, else, case, break},
  keywordstyle=\color{blue}\bfseries,
  ndkeywords={class, export, boolean, throw, implements, import, this},
  ndkeywordstyle=\color{darkgray}\bfseries,
  identifierstyle=\color{black},
  sensitive=false,
  comment=[l]{//},
  morecomment=[s]{/*}{*/},
  commentstyle=\color{purple}\ttfamily,
  stringstyle=\color{red}\ttfamily,
  morestring=[b]',
  morestring=[b]"
}

\usepackage{csquotes}

\usepackage{epigraph} % per le frasi inizio capitolo

\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhead[LEO]{\slshape \leftmark} %section
\fancyhead[REO]{\thepage}
\setlength{\headheight}{14.5pt}

%\usepackage{etoolbox}

\usepackage[italian, textsize=tiny]{todonotes}
\setlength{\marginparwidth}{2cm}

%\usepackage{refcheck}

\usepackage{tikz}
\usetikzlibrary{arrows}

\usepackage{titlesec}

\newenvironment{usecaseenv}{
    \def\arraystretch{2}
    \begin{tabular}{p{3cm}p{10cm}}\hline
}{
    \hline\end{tabular}
    \def\arraystretch{1}
}

\newenvironment{characteristicsEnv}{
    \def\arraystretch{2}
    \begin{tabular}{lp{8cm}}\hline
}{
    \hline\end{tabular}
    \def\arraystretch{1}
}

\newcommand\addheading[1]{
    \multicolumn{2}{c}{\textbf{\textit{#1}}}\\ \hline
}

\newcommand\addrow[2]{
    \textbf{#1}
    &\begin{minipage}[t][][t]{10cm}
       #2
    \end{minipage}\\
}

\newcommand\addrowservice[2]{
    \textbf{#1}
    &\begin{minipage}[t][][t]{8cm}
       #2
    \end{minipage}\\
}

% The actual command definition
\let\oldFigureName\figurename %save the old definition of the caption's figure name
\newcommand{\usecase}[5]{
    \vspace*{0.5cm} % adds a bit of padding to make it look nicer
    \renewcommand{\figurename}{Use case} %call figure name "Use case" instead
    \begin{figure}[htbp]
        \begin{center}
            \begin{usecaseenv}
                \addheading{#1} 
                \addrow{Use case:}{#2}
                \addrow{Soggetti:}{#3}
                \addrow{Obiettivi:}{#4}
            \end{usecaseenv}
        \end{center}
        \caption{#5}
    \end{figure}
    \renewcommand{\figurename}{\oldFigureName} %reset caption figure name
}

\let\oldFigureName\figurename %save the old definition of the caption's figure name
\newcommand{\serviceCharacteristics}[6]{
    \vspace*{0.5cm} % adds a bit of padding to make it look nicer
    \renewcommand{\figurename}{} %call figure name "Use case" instead
    \begin{figure}[H]
        \begin{center}
            \begin{characteristicsEnv}
                \addheading{Caratteristiche}
                \addrowservice{Partecipanti:}{#1}
                \addrowservice{Architettura software:}{#2}
                \addrowservice{Architettura hardware:}{#3}
                \addrowservice{Tipo di dato condiviso:}{#4}
                \addrowservice{Licenza:}{#5}
            \end{characteristicsEnv}
        \end{center}
        %\caption{}
    \end{figure}
    \renewcommand{\figurename}{\oldFigureName} %reset caption figure name
}

\raggedbottom

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\newgeometry{centering}
% Frontespizio
\begin{titlepage}
    \begin{center}
        \includegraphics[width=\textwidth]{images/Logo.jpg}\\
        {\large{\em Corso di Laurea in Informatica per la comunicazione digitale}}
    \end{center}
    \vspace{12mm}
    \begin{center}
        {\huge{\bf Streaming decentralizzato di}}\\
        \vspace{4mm}
        {\huge{\bf contenuti audiovisivi}}\\
    \end{center}
    \vspace{12mm}
    \begin{flushleft}
        {\large{\bf Relatore:}}
        {\large{Trentini Andrea}}\\
        %{\large{\bf Correlatore:}}
        %{\large{...}}\\
    \end{flushleft}
    \vfill
    \begin{flushright}
        \parbox{1.7in}{
        {\large{\bf Tesi di Laurea di:}}\\
        {\large{Mirko Milovanovic}}\\
        {\large{\bf Matricola: \normalfont 870671}}
        }
    \end{flushright}
    \vfill
    \begin{center}
        {\large{\bf Anno Accademico 2023-2024}}
    \end{center}
\end{titlepage}


\newpage
\thispagestyle{empty}
{\raggedleft \large \sl Questo lavoro \`{e} dedicato ai miei genitori,\\ a mia sorella, suo marito e i miei nipoti.\\
	
	\vspace{2cm}
	
	``Do you see how you've grown? Don't be sorry then''
	
	\bigskip
	
	\--- Porter Robinson\\}


\chapter*{Ringraziamenti}
\pagenumbering{Roman}
\addcontentsline{toc}{chapter}{Ringraziamenti}

Desidero esprimere la mia più sincera gratitudine a tutte le persone che hanno contribuito, direttamente o indirettamente, alla realizzazione di questa tesi.

Innanzitutto, ringrazio il Professor Andrea Trentini per la sua guida esperta, i preziosi consigli e il supporto costante durante tutto il percorso di ricerca e stesura di questo lavoro.

Un ringraziamento speciale va alla comunità di PeerTube e Framasoft, non solo per aver creato una piattaforma innovativa che è stata oggetto di questo studio, ma anche per il loro impegno nel promuovere soluzioni open source e decentralizzate.

\

Vorrei esprimere la mia gratitudine tutti gli amici e colleghi volontari dell'Osservatorio Astronomico `Giovanni Virginio Schiaparelli' che mi hanno accompagnato durante il percorso universitario, per il loro supporto morale, l'incoraggiamento e i momenti di confronto che hanno arricchito questa esperienza.

\

Un profondo ringraziamento va alla mia famiglia, per il loro incondizionato sostegno e la enorme pazienza dimostrata durante tutto il mio percorso accademico. Senza il loro supporto, questo traguardo non sarebbe stato possibile.

Infine, un pensiero di gratitudine a tutti coloro che, pur non essendo citati esplicitamente, hanno contribuito in vari modi alla realizzazione di questo lavoro.

\newpage
\thispagestyle{plain}

\cleardoublepage
\addcontentsline{toc}{chapter}{\contentsname}
\tableofcontents
\thispagestyle{plain}

\chapter{Introduzione}
\pagenumbering{arabic}
\setcounter{page}{1}

Fin dai suoi albori Internet, nato da ARPAnet, svolge un ruolo importantissimo nella vita di tutti noi, che sia condividere informazioni militari, utilizzare servizi erogati via Web, o più recentemente guardare contenuti audiovisivi ``on-the-go'', ovvero quello di connettere le persone intorno al globo nei più svariati modi possibili attraverso l'utilizzo di calcolatori come computer e/o dispositivi mobili ``connessi''.

Negli anni e per come è stato concepito Internet stesso architetturalmente, si sono venuti a formare veri metodi di comunicazione tra gli utilizzatori e gli erogatori di servizi Internet, più o meno sicuri, efficaci o resilienti rispetto a tematiche come la privacy dei dati, la centralizzazione e costi di operazione.

Il modello Client/Server è certamente il più diffuso, reso famoso dall'imponente World Wide Web, il modo più intuitivo di utilizzare Internet ma certamente non l'unico.\cite{w3c} Questa architettura, specialmente nell'ambito della trasmissione di contenuti audiovisivi in streaming, presenta notevoli sfide tecniche ed economiche. L'infrastruttura centralizzata richiede server potenti e costosi che devono gestire simultaneamente migliaia di connessioni, con un consumo di banda che cresce linearmente con il numero di spettatori.

Negli ultimi anni, diverse piattaforme hanno cercato di risolvere questo problema attraverso l'adozione di tecnologie peer-to-peer (P2P) per la distribuzione dei contenuti. Tra queste, PeerTube si distingue come una delle soluzioni più promettenti, combinando una struttura federata con tecnologie di streaming P2P che promettono di ridurre significativamente il carico sui server centrali.

Questa tesi si propone di analizzare criticamente le affermazioni fatte dagli sviluppatori di PeerTube riguardo l'efficienza e l'efficacia del loro approccio P2P nel contesto dello streaming video. Partiremo da un'analisi del panorama attuale dello streaming centralizzato, ne evidenzieremo i limiti, per poi esplorare le alternative decentralizzate e concentrarci su PeerTube, ricreando e ampliando i test condotti dai suoi sviluppatori per verificarne empiricamente le prestazioni.

\section{Il problema dello streaming centralizzato}

Un sistema Client/Server tradizionale per lo streaming video presenta diverse problematiche critiche:

\begin{itemize}
    \item \textbf{Scalabilità limitata}: I server centrali devono gestire tutto il traffico in uscita, con costi di banda che crescono linearmente con il numero di spettatori.
    \item \textbf{Single Point of Failure}: Se il server centrale subisce un'interruzione, tutti i client perdono l'accesso al servizio.
    \item \textbf{Costi infrastrutturali elevati}: Mantenere server capaci di gestire picchi di traffico richiede investimenti significativi.
    \item \textbf{Centralizzazione del controllo}: Poche entità controllano le piattaforme più popolari, con potenziali implicazioni per la libertà di espressione e la privacy.
\end{itemize}

\section{Le alternative decentralizzate e P2P}

Le tecnologie peer-to-peer offrono un approccio alternativo che potrebbe risolvere molti di questi problemi:

\begin{itemize}
    \item \textbf{Distribuzione del carico}: Ogni client può anche fungere da distributore per altri client, riducendo il carico sul server originale.
    \item \textbf{Maggiore resilienza}: L'assenza di un punto centrale di fallimento rende il sistema più robusto.
    \item \textbf{Riduzione dei costi}: I costi di banda vengono distribuiti tra i partecipanti anziché essere sostenuti da un unico fornitore.
    \item \textbf{Decentralizzazione del controllo}: Nessuna entità singola può controllare completamente il flusso di informazioni.
\end{itemize}

Tra le varie piattaforme che utilizzano questo approccio, PeerTube ha attirato la nostra attenzione per la sua architettura ibrida che combina federazione e P2P, e per le affermazioni dei suoi sviluppatori riguardo l'efficienza di questo approccio. In particolare, un articolo pubblicato dal team di PeerTube sostiene che la loro implementazione P2P può ridurre il carico sul server di origine fino all'80\%, una cifra che merita un'analisi approfondita e una verifica indipendente.

\chapter{Stato dell'arte}
\epigraph{In questo capitolo analizzeremo il panorama attuale delle tecnologie di streaming, confrontando approcci centralizzati e decentralizzati per comprendere i loro punti di forza e debolezza.}{}

\section{Modelli di comunicazione in rete}

\subsection{Client/Server e il Web 2.0}

Un sistema Client/Server è un tipo di computazione distribuita in cui i clienti effettuano delle richieste verso un server che a sua volta risponde con i dati/servizi richiesti restando in attesa. I client possono essere di vario tipo e trovarsi ovunque nel globo e in generale integrano una parte hardware (smartphone, PCs, \dots) ad una software (applicazioni GUI, web browser, \dots). I server, invece, sono delle macchine specializzate spesso raggruppate assieme in grandi data center, interconnesse tra di loro per fornire uno o più servizi a molteplici client contemporaneamente.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/Client-server-model.png}
    \caption{Modello Client/Server tradizionale}
\end{figure}

Questo modello ha dominato l'era del Web 2.0, caratterizzata da:

\begin{itemize}
    \item Piattaforme centralizzate con contenuti generati dagli utenti
    \item Elevata interattività e social networking
    \item Controllo dei dati da parte delle grandi aziende tecnologiche
    \item Monetizzazione tramite pubblicità e raccolta dati
\end{itemize}

Nonostante i vantaggi in termini di semplicità d'uso e accessibilità, questo modello ha portato a:

\begin{itemize}
    \item Forte centralizzazione del potere da parte di poche "Big Tech"
    \item Elevati costi di infrastruttura
    \item Problemi di privacy e controllo dei dati personali
    \item Vulnerabilità a censura e manipolazione dei contenuti
\end{itemize}

\subsection{Peer-to-Peer}

Il modello peer-to-peer rappresenta un approccio alternativo in cui ogni nodo della rete può fungere sia da client che da server, eliminando la necessità di un'infrastruttura centralizzata. Questo modello è alla base di molte tecnologie del cosiddetto Web 3.0, caratterizzato da:

\begin{figure}[H]
    \centering
    \includegraphics[width=250pt]{images/p2p-network.png}
    \caption{Modello P2P}
\end{figure}

\begin{itemize}
    \item Decentralizzazione del controllo e distribuzione del carico
    \item Maggiore privacy e sovranità sui dati personali
    \item Resilienza a censura e fallimenti di singoli nodi
    \item Riduzione dei costi infrastrutturali
\end{itemize}

Tuttavia, le soluzioni P2P presentano anche alcune sfide:

\begin{itemize}
    \item Maggiore complessità tecnica
    \item Possibili problemi di latenza e qualità del servizio
    \item Difficoltà nel garantire contenuti legali e moderazione
    \item Sfide tecniche come il NAT traversal e la connettività tra peer
\end{itemize}

\section{Modelli di distribuzione dei dati in rete}

La distribuzione dei dati nelle reti di computer può seguire diversi modelli, ciascuno con caratteristiche specifiche e casi d'uso ottimali. I tre principali modelli di distribuzione sono: unicast, multicast e broadcast. Comprendere questi modelli è essenziale per analizzare le soluzioni di streaming video, poiché ciascuno offre vantaggi e svantaggi in termini di efficienza, scalabilità e facilità di implementazione.

\subsection{Unicast}

Il modello unicast consiste nella trasmissione di dati da un mittente a un singolo destinatario specifico. Questo è il modello predominante su Internet e viene utilizzato dalla maggior parte dei servizi di streaming video tradizionali.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/Unicast.png}
    \caption{Modello di comunicazione Unicast.}
\end{figure}

\textbf{Caratteristiche principali:}
\begin{itemize}
    \item \textbf{Connessione uno-a-uno:} Ogni client stabilisce una connessione dedicata con il server.
    \item \textbf{Consumo di banda:} La banda richiesta sul server aumenta linearmente con il numero di client.
    \item \textbf{Controllo individuale:} Ogni client può controllare indipendentemente la riproduzione (pausa, riavvolgimento, ecc.).
    \item \textbf{Personalizzazione:} Permette contenuti e pubblicità personalizzati per ogni utente.
\end{itemize}

\textbf{Implicazioni per lo streaming video:}
Il modello unicast è semplice da implementare e garantisce un elevato controllo sull'esperienza utente, ma diventa estremamente inefficiente quando molti utenti richiedono lo stesso contenuto contemporaneamente. Un server che trasmette un video in HD a 1000 spettatori deve inviare 1000 copie identiche dello stesso flusso dati, con conseguente consumo elevato di banda e risorse del server \cite{wiki:Unicast}.

\subsection{Multicast}

Il multicast è un modello di distribuzione in cui i dati vengono inviati a un gruppo specifico di destinatari simultaneamente. Anziché inviare più copie dei dati, il server invia una singola copia che viene replicata dai router di rete solo quando necessario.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/Multicast.png}
    \caption{Modello di comunicazione Multicast.}
\end{figure}

\textbf{Caratteristiche principali:}
\begin{itemize}
    \item \textbf{Efficienza della banda:} Indipendentemente dal numero di ricevitori, il traffico generato rimane costante fino ai punti di biforcazione nella rete.
    \item \textbf{Gruppi di destinazione:} I client si iscrivono a gruppi multicast specifici per ricevere determinati flussi di dati.
    \item \textbf{Supporto dell'infrastruttura:} Richiede router compatibili con il protocollo Internet Group Management Protocol (IGMP).
    \item \textbf{Controllo limitato:} Tutti i client ricevono lo stesso flusso contemporaneamente, limitando le opzioni di controllo individuale.
\end{itemize}

\textbf{Implicazioni per lo streaming video:}
Il multicast è teoricamente ideale per eventi live con molti spettatori, poiché riduce drasticamente il carico sui server e sulla rete backbone. Tuttavia, la sua adozione su Internet pubblico è limitata perché molti ISP e router domestici non supportano pienamente il routing multicast. È più comunemente utilizzato in reti aziendali, IPTV e altre reti gestite \cite{wiki:Multicast}.

\subsection{Broadcast}

Il broadcast consiste nell'invio di dati a tutti i dispositivi all'interno di una rete. A differenza del multicast, che indirizza un gruppo specifico, il broadcast raggiunge indiscriminatamente tutti i nodi in un dominio di broadcast.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/Broadcast.png}
    \caption{Modello di comunicazione Broadcast.}
\end{figure}

\textbf{Caratteristiche principali:}
\begin{itemize}
    \item \textbf{Copertura totale:} Raggiunge tutti i dispositivi nella rete locale.
    \item \textbf{Nessuna configurazione client:} I destinatari non devono iscriversi o configurare nulla per ricevere i dati.
    \item \textbf{Limitazioni di scala:} Generalmente limitato a singoli segmenti di rete a causa dei problemi di congestione che potrebbe causare.
    \item \textbf{Utilizzo inefficiente:} Molti destinatari potrebbero non essere interessati ai dati trasmessi.
\end{itemize}

Nelle nostre analisi, andremo a considerare solo soluzioni Unicast in quanto si tratta del modello più diffuso e utilizzato, anche perché le tecnologie di streaming che analizzeremo sono tutte implementate a livello applicativo dello stack TCP/IP e quindi operano naturalmente in modalità unicast.

\textbf{Implicazioni per lo streaming video:}
Il broadcast è raramente utilizzato per lo streaming video su Internet, principalmente a causa delle sue limitazioni di scala e dell'inefficienza. È più adatto per scopi come la scoperta di dispositivi in reti locali o la trasmissione televisiva tradizionale. Nel contesto delle reti IP, il broadcast è generalmente considerato obsoleto per applicazioni di streaming a favore di approcci più mirati come multicast o tecnologie come CDN e P2P \cite{wiki:Broadcasting_networking}.

\subsection{Confronto e applicazioni nello streaming video}

\begin{table}[H]
\centering
\caption{Confronto tra modelli di distribuzione dei dati per lo streaming video.}
\label{tab:distribution-models}
\begin{tabular}{lccc}
\toprule
\textbf{Caratteristica} & \textbf{Unicast} & \textbf{Multicast} & \textbf{Broadcast} \\
\midrule
Scalabilità & Limitata & Eccellente & Molto limitata \\
Controllo utente & Completo & Limitato & Assente \\
Supporto Internet & Universale & Limitato & Non utilizzato \\
Efficienza larghezza di banda & Bassa & Alta & Molto bassa \\
Personalizzazione contenuti & Possibile & Difficile & Impossibile \\
Implementazione CDN & Semplice & Complessa & Non applicabile \\
\bottomrule
\end{tabular}
\end{table}

Le soluzioni di streaming decentralizzate come PeerTube cercano di combinare i vantaggi del multicast (efficienza della banda) con l'universale supporto dell'unicast, utilizzando connessioni peer-to-peer per distribuire il carico. Questo approccio "multicast simulato" permette di raggiungere un'efficienza simile al multicast nativo senza richiedere supporto specifico da parte dell'infrastruttura di rete.

Le applicazioni CDN (Content Delivery Network) rappresentano un altro approccio per migliorare l'efficienza dell'unicast, posizionando copie dei contenuti più vicino agli utenti finali, ma senza modificare il modello di comunicazione di base \cite{wiki:Content_delivery_network}.

Nell'evoluzione dello streaming video, stiamo assistendo a un crescente interesse verso soluzioni ibride che combinano questi diversi modelli per ottimizzare l'esperienza utente, l'efficienza della rete e i costi operativi.

\section{Casi d'uso per lo streaming decentralizzato}

Vediamo degli esempi di come questa interazione potrebbe essere svolta:

\usecase{Esempio d'interazione ``one to many''}{Un utente davanti al proprio computer vorrebbe condividere quello che vede sullo schermo con i propri amici o followers}{Utente principale, viewers, computer, connessione internet}{Condivisione in live streaming di un contenuto a schermo via internet con TCP/IP}{}

\usecase{Esempio d'interazione ``many to many''}{Più utenti al proprio computer vorrebbero comunicare e interagire tra di loro contemporaneamente simil conference-call}{Utenti multipli, computer, connessione internet, microfono, telecamera}{Live streaming e interazione real-time tra utenti via internet con TCP/IP}{}

\usecase{Esempio d'interazione ``one to many''}{Un’azienda per questioni legate alla sicurezza sul lavoro si ritrova con la necessitò di dover fare dei ``workshop'' in diretta ai propri dipendenti con diverse locazioni sparse per il nel mondo senza utilizzare però grandi servizi cloud dato l’elevato costo di banda e di noleggio del servizio per singolo utente finale, in questo caso il singolo dipendente}{Dipendenti, azienda}{Video streaming dei ``workshop'' per i dipendenti sparsi per il mondo}{}

\usecase{Esempio d'interazione ``one to many''}{Un gruppo di amici deve svolgere un progetto universitario assieme e quindi interagire tra di loro facendo pair programming condividendo lo schermo gli uni con gli altri. Per questioni di privacy e sicurezza non vuole utilizzare un servizio pubblico come Discord in quanto vorrebbero tenere tutto segreto fino al giorno della presentazione}{Studenti}{Pair programming}{}

\usecase{Esempio d'interazione ``one to many''}{Una casa produttrice di film emergente vuole condividere i nuovi film in produzione con dei trailer ma a causa di dispute legate ai DRM, copyright e content strike di altre aziende più grandi non vuole utilizzare dei servizi già esistenti con EULA molto restringenti ma vuole avere il controllo dei propri diritti sul contenuto creato da essa stessa}{Filmmakers, appassionati di film}{Condivisione degli ultimi trailer per i film prodotti dalla casa}{}

\usecase{Esempio d'interazione ``one to many''}{Un gruppo di amici vuole fare una serata di gioco online e vuole condividere il proprio schermo con gli altri giocatori per poter giocare assieme}{Gamer}{Condivisione dello schermo per giocare assieme}{}

\break

In sintesi, l'analisi dei casi d'uso evidenzia la necessità di una soluzione di streaming decentralizzata e a licenza libera, capace di operare in modalità uno-a-molti o molti-a-molti, senza affidarsi a servizi cloud proprietari e senza richiedere il deploy di una complessa infrastruttura hardware globale. I requisiti fondamentali, soprattutto in relazione all'elevato fabbisogno di banda tipico dei contenuti video, si declinano nei seguenti scenari applicativi:

\hfill\break
\textbf{Commerciale:}
\begin{itemize}
    \item Streaming di eventi o riunioni interne,
    \item Assistenza remota,
    \item Conference calls,
    \item Possibilità di operare sia come utente che come provider/distributore,
    \item Ottimizzazione dei costi e del consumo della banda.
\end{itemize}

\hfill\break
\textbf{Educazionale:}
\begin{itemize}
    \item Trasmissione in diretta di corsi e lezioni.
\end{itemize}

\hfill\break
\textbf{Sociale:}
\begin{itemize}
    \item Organizzazione di lan party,
    \item Supporto per streaming di gaming e attività live da parte di streamer,
    \item Conference calls in piccoli gruppi,
    \item Impiego per telecamere di sicurezza,
    \item Moderazione dei contenuti online.
\end{itemize}

\hfill\break
\textbf{Istituzionale:}
\begin{itemize}
    \item Comunicazioni video in situazioni di emergenza.
\end{itemize}

\section{Panoramica delle piattaforme di streaming esistenti}

\subsection{Soluzioni centralizzate}

\subsubsection{Twitch}

Twitch è una piattaforma di live streaming di proprietà di Amazon lanciata nel 2011, originariamente specializzata nella trasmissione in diretta di videogiochi, eSports ed eventi riguardanti il mondo videoludico.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/twitchHome.png}
    \caption{Home page di Twitch.}
\end{figure}

Una delle più famose e grandi, la piattaforma è stata originariamente sviluppata come una controparte di streaming per Justin.tv, una piattaforma di streaming generale. Tuttavia, Twitch si è concentrata esclusivamente sui contenuti di videogiochi e di eSports, anche se oggi rimane tutt'ora la scelta "de-facto" per molti utenti non solo per lo streaming di contenuti videoludici ma anche per lo "streaming general purpose" come ad esempio lo streaming di musica, arte, cucina e di varie attività creative.

Negli anni successivi, ha visto una rapida crescita e ha attirato una vasta gamma di creatori di contenuti, dalle grandi organizzazioni di esports ai singoli streamer indipendenti, fino ad oggi con una user base di circa 3 milioni di viewers e 1.5 milioni di broadcaster giornalieri rispettivamente.

Twitch offre molti servizi sotto un unico sito web accessibile con un semplice browser:

\serviceCharacteristics{Chiunque con un account può condividere e guardare}
{Centralizzata}
{Servizio accessibile via browser o applicazione mobile}
{Stream video e testo per funzionalità di live chat}
{Proprietaria con contratto di utilizzo `EULA'}

\subsubsection{YouTube}

Youtube è una piattaforma di sharing online di video statici, di proprietà di Google, specializzata nella condivisione globale di video generici con funzionalità aggiuntive di social media, monetizzazione e live streaming.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/youtubeHome.png}
    \caption{Home page di Youtube.}
\end{figure}

La compagnia è stata lanciata nel febbraio 2005 come indipendente ed è poi stata successivamente acquisita da Google. Al momento viene considerata la piattaforma più grande e longeva di questo segmento, con più di 2.5 miliardi di utenti mensili e milioni di ore di video condivisi ogni giorno. Dall'acquisizione, YouTube ha espanso la propria offerta al di fuori della sola condivisione di video "amatoriali", includendo contenuti come film di produzione professionale, video musicali ufficiali, documentari, news, ecc. Ha anche integrato la piattaforma pubblicitaria AdSense, sempre di proprietà di Google, permettendo a tutti gli utenti amatoriali o professionali approvati di poter ricevere un ricavo economico dalle pubblicità e dal marketing presenti sul sito.

\serviceCharacteristics{Chiunque sul web}{Servizio accessibile via browser o applicazione mobile}{Centralizzata con utilizzo di CDN}{Video statici, live stream}{Proprietaria con contratto di utilizzo `EULA'}

\subsection{Soluzioni decentralizzate e P2P}

\subsubsection{Tahoe-LAFS}

Tahoe-LAFS è un sistema di file distribuito, open source, decentralizzato e sicuro che permette agli utenti di memorizzare e condividere file in un ambiente di rete distribuita chiamata `Grid'. Sviluppato da un gruppo di ricercatori dell'Università di Maryland, dal 2007 ed è stato rilasciato come software open source sotto licenza GPL. Tahoe-LAFS è stato progettato per essere un sistema di file distribuito sicuro, affidabile e scalabile, in modo da poter essere utilizzato in ambienti di rete distribuita, dato che promette di essere un sistema `provider-independent', ovvero che i fornitori dei server intermediari non hanno mai la possibilità di accedere o modificare i dati memorizzati dagli utenti finali perché che non sono loro a garantire la confidenzialità, l'integrità o l'assoluta disponibilità dei dati, ma sono i client finali a farlo. 

Alla base, Tahoe-LAFS è essenzialmente un sistema di archiviazione chiave-valore. L'archivio utilizza delle corte stringhe, circa 100 byte, chiamate `capabilities' come chiavi e dati arbitrari come valori.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/tahoe-LAFS.logo.png}
    \caption{Tahoe-LAFS logo.}
\end{figure}

Si possono condividere queste `capabilities' per dare agli altri accesso a determinati valori sulla `Grid'. Ad esempio, si può dare la possibilità di lettura ad un amico e conservare il permesso di scrittura per te stessi.
Per eliminare un valore, basta dimenticare (cioè eliminare) la chiave della `capability', e, una volta fatto sarà impossibile recuperare i dati. I server di archiviazione però hanno un modo per fare `garbage-collection' da condivisioni non referenziate.


In aggiunta al sistema chiave-valore, viene affiancato un livello i file-storage classico, che consente di condividere, con altri utenti, sotto-directory senza, ad esempio, rivelare l'esistenza o il contenuto delle directory principali.

Come detto prima, sono i clienti a garantire l'integrità e la confidenzialità dei dati, e questo viene realizzato grazie alla crittografia che viene eseguita su ogni `capability' prima di essere caricata sul `Grid'. Ogni valore viene prima crittografato con una chiave asimmetrica e poi spezzettato in parti più piccole, e più maneggiabili. Questi segmenti diventano poi effettivamente gli `share' che verranno memorizzati nei noti della rete, che ricordiamo, svolgono solo la funzione di memorizzazione dei dati, gli utenti non si affidano a loro per altro. \cite{tahoelafsAbouttahoerstTrunkdocs} \cite{torprojectHeartTahoeLAFS}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/tahoe-simple-data-flow.png}
    \caption{Tahoe-LAFS simple data flow.}
\end{figure}

\serviceCharacteristics{Utenti e server di terze parti}{Software client lato utente}{Decentralizzata e `provider-indipendent'}{Qualsiasi tipo di file binario}{GPL}

\subsubsection{IPFS}
IPFS o `InterPlanetary File System' è una suite di protocolli e librerie open source per la condivisione di file in un ambiente di rete distribuita utilizzando meccanismi di `content-addressing'. IPFS è stato sviluppato da Protocol Labs, un'azienda di ricerca e sviluppo nel 2014.

IPFS punta a creare un file system condiviso da una rete di nodi decentralizzata che comunica attraverso P2P, dove i singoli file sono organizzati come blocchi indipendentemente individuabili ed immutabili (ovvero che non possono essere modificati ma solo aggiunti o eliminati) con degli identificatori chiamati `CID (Content identifiers)' memorizzati in un database distribuito chiamato `DHT (Distributed Hash Table)' che viene condiviso con ogni singolo nodo della rete al fine di facilitare il routing dei dati attraverso essa stessa.

Uno dei problemi di IPFS è che per design stesso, ogni singolo file è visibile a tutti i nodi della rete e quindi non è possibile creare un sistema di condivisione di file privati, ma solo di file pubblici, che però volendo possono essere crittografati, impedendo la lettura dei dati da parte di attori terzi. \cite{ipfsWhatIPFS} \cite{ipfsIPFSWhitepaper}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/Data-sharing-on-IPFS-by-owner.png}
    \caption{IPFS data flow. \cite{ResearchBasedDataRightsManagementUsingBlockchainOverEthereumNetwork}}
\end{figure}

\serviceCharacteristics{Nodi della rete}{Protocolli e software lato client}{Decentralizzata simil Blockchain}{Qualsiasi tipo di file binario}{MIT}

\subsubsection{PeerTube}
PeerTube è un servizio di video sharing open source, federalizzato e decentralizzato (lato client), basato su protocolli peer-to-peer come `WebTorrent', `WebRTC' e altre tecnologie web standard.
Fa parte del cosiddetto `Fediverse', un insieme di server interconnessi che comunicano tramite ActivityPub, un protocollo di comunicazione aperto per creare reti federate.
Inizialmente creato come una piattaforma di video sharing per i creatori di contenuti indipendenti, è stato progettato per essere estensibile e adattabile a qualsiasi tipo di contenuto video che rispetti i termini delle singole istanze che vengono messe a disposizione pubblicamente.

Il funzionamento è del tutto simile ad altre piattaforme video tipo (YouTube, Vimeo, Dailymotion, ecc.) con supporto per video statici e livestream, ma con la differenza che i video possono essere memorizzati e condivisi non solo dalle singole istanze della federazione attraverso il normale HTTP ma anche tra i client finali usando P2P per alleggerire il carico di banda.
PeerTube è iniziato come progetto indipendente da un singolo sviluppatore che poi è stato affiancato dalla no-profit Framasoft. \cite{peertubeAbout} \cite{wiki:ActivityPub} \cite{activitypubActivityPubRocks}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/peerTubeHome.png}
    \caption{PeerTube.}
\end{figure}

\serviceCharacteristics{Utenti registrati e non delle singole istanze}{Browser web e server indipendenti}{Federalizzata e decentralizzata P2P}{Video statici e livestream}{AGPLv3+}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/peerTubeItalia.png}
    \caption{Una istanza di PeerTube Italiana.}
\end{figure}

\subsubsection{Ace Stream}
Ace Stream è un software proprietario di video streaming basato su P2P, sviluppato da un gruppo di sviluppatori russi, che permette agli utenti di trasmettere in diretta video e audio, riprodurre file multimediali, e ricevere e condividere contenuti in tempo reale. Il software è stato rilasciato per la prima volta nel 2013 e da allora è stato scaricato più di 100 milioni di volte. Ace Stream offre una vasta gamma di funzionalità che lo rendono popolare tra gli utenti che desiderano guardare contenuti in streaming. Utilizzando la tecnologia P2P, il software consente agli utenti di trasmettere video e audio in tempo reale, senza dover attendere il completamento del download. Questo significa che gli utenti possono godere di una riproduzione fluida e senza interruzioni, anche con connessioni internet più lente.

\begin{figure}[htb]
    \centering
    \includegraphics[width=\textwidth]{images/Ace_Stream_logo.png}
    \caption{PeerTube.}
\end{figure}

Inoltre, Ace Stream supporta la riproduzione di file multimediali locali, consentendo agli utenti di guardare i propri film, serie TV e altri contenuti salvati sul proprio dispositivo. Il software supporta una vasta gamma di formati video e audio, garantendo un'alta compatibilità.

Un'altra caratteristica interessante di Ace Stream è la possibilità di ricevere e condividere contenuti in tempo reale. Gli utenti possono creare i propri canali di streaming e condividere i propri contenuti con altri utenti. Questo rende il software ideale per gli appassionati di sport, che possono trasmettere eventi sportivi in diretta e condividerli con altri appassionati.

Ace Stream è disponibile per diverse piattaforme, tra cui Windows, Mac, Linux e Android, il che lo rende accessibile a un vasto pubblico. Inoltre, il software è gratuito da scaricare e utilizzare, rendendolo ancora più attraente per gli utenti.

In conclusione, Ace Stream è un software potente e versatile per lo streaming di video e audio. Grazie alla sua tecnologia P2P, offre una riproduzione fluida e senza interruzioni, consentendo agli utenti di godersi i propri contenuti preferiti in tempo reale. Con la possibilità di condividere contenuti e creare canali di streaming, Ace Stream offre un'esperienza di streaming interattiva e coinvolgente. \cite{acestreamAnnouncementStream} \cite{archiveStream}

\serviceCharacteristics{Utenti registrati e non delle singole istanze}{Browser web e server indipendenti}{Federalizzata e decentralizzata P2P}{Video statici e livestream}{AGPLv3+}

\chapter{PeerTube: architettura e tecnologie}

Tra tutti i progetti open source che si occupano di decentralizzazione e P2P, PeerTube è uno dei più interessanti e promettenti. In questo capitolo, esamineremo l'architettura e le tecnologie alla base di PeerTube, analizzando come il progetto si è evoluto nel corso degli anni e quali sono le sue caratteristiche principali.

\section{Storia e evoluzione del progetto}

PeerTube è nato nel 2017 come progetto di un singolo sviluppatore di nome \textit{Chocobozzz} e successivamente poi supportato dall'organizzazione non profit francese Framasoft, con l'obiettivo di creare un'alternativa libera e decentralizzata a piattaforme come YouTube. Da allora, ha visto una crescita costante sia in termini di funzionalità che di adozione.
Essendo una piattaforma di tipo ActivityPub, PeerTube fa parte del cosiddetto Fediverse, un network federato di piattaforme interconnesse. Questo significa che gli utenti di PeerTube possono interagire con utenti di altre piattaforme compatibili con ActivityPub, come Mastodon, Pleroma e Pixelfed.\cite{wiki:ActivityPub}

Ogni istanza di PeerTube fornisce un sito web, del tutto simile ad altre piattaforme come YouTube, per navigare e guardare video ed è, per impostazione predefinita, indipendente dalle altre in termini di aspetto, funzionalità e regole.

Diverse istanze con regole comuni (ad esempio, consentire contenuti simili o richiedere la registrazione) possono formare federazioni, in cui seguono i video di altre istanze, pur mantenendo i contenuti archiviati solo sull'istanza che li ha pubblicati.

Le federazioni sono indipendenti tra loro e asimmetriche: un'istanza può seguire un'altra per visualizzarne i video, senza reciprocità necessarie. Gli amministratori delle istanze possono scegliere di duplicare singoli video o intere istanze amiche, incentivando così la creazione di comunità con larghezza di banda condivisa.

Alcune tappe importanti nella storia di PeerTube includono:
\begin{itemize}
    \item \textbf{2017}: Lancio del progetto da parte di \textit{Chocobozzz}
    \item \textbf{2018}: Supporto da parte di Framasoft e lancio della versione 1.0
    \item \textbf{2021}: Lancio della versione 3.0 con introduzione del supporto per i livestream e miglioramenti all'interfaccia utente
    \item \textbf{2021}: Introduzione di funzionalità di moderazione avanzate e supporto per i sottotitoli
    \item \textbf{2022}: Il Garante Europeo della Protezione dei Dati (EDPS) lancia EU Video, una piattaforma video basata su PeerTube per le istituzioni, gli enti e le agenzie dell'Unione Europea, come progetto pilota su ActivityPub. Viene chiuso ufficialmente nel 2024.
\end{itemize} \cite{wiki:PeerTube}

\section{Stack tecnologico}

PeerTube è combina diverse tecnologie per fornire una piattaforma di streaming video decentralizzata e federata. La sua architettura si basa su un mix di tecnologie web moderne, tra cui Node.js, PostgreSQL, WebRTC etc.

Interessante caratteristica è che PeerTube è progettato per essere estensibile consentendo agli sviluppatori e admin di aggiungere nuove funzionalità e miglioramenti senza dover modificare il codice sorgente principale. Questo approccio facilita la creazione di plugin e moduli personalizzati, che possono essere utilizzati per estendere le funzionalità della piattaforma.
Per esempio, di default, PeerTube non ha alcun supporto integrato per le chat room in diretta, ma è possibile installare un plugin molto popolare che consente di integrare un sistema di chat in tempo reale durante le dirette streaming. \cite{wiki:PeerTube}

Riguardo invece la parte di distribuzione dei video, fino alla versione 6.0.0, PeerTube supportava sia HLS su WebRTC-P2P (noto anche come `HLS con P2P') sia WebTorrent.

WebTorrent è una re-implementazione del protocollo BitTorrent su WebRTC. Ogni server PeerTube funge da tracker torrent, mentre i browser degli utenti che visualizzano un video partecipano attivamente alla sua distribuzione.

\

HLS, normalmente implementato con hls.js, non include funzionalità P2P. PeerTube ha esteso questa tecnologia con un loader personalizzato, che scarica contemporaneamente i segmenti video sia dal server web sia da altri spettatori tramite WebRTC, riducendo così il carico sui server e distribuendo la banda attraverso il P2P.

I video sono resi disponibili per il download tramite HTTP, ma la riproduzione privilegia un sistema peer-to-peer utilizzando HLS e WebRTC P2P. \cite{wiki:PeerTube} \cite{framablogPeerTubeOut}

\subsection{Architettura generale}

PeerTube utilizza un'architettura ibrida che combina:
\begin{itemize}
    \item Un backend basato su Node.js e TypeScript
    \item Un frontend realizzato con Angular
    \item Un sistema di storage per i video (locale o distribuito)
    \item Un database PostgreSQL per la persistenza dei dati
    \item Un sistema di federazione basato su ActivityPub
    \item Tecnologie P2P per la distribuzione dei contenuti (Novage P2P Media Loader)
\end{itemize} \cite{githubGitHubChocobozzzPeerTube}

\subsection{Streaming video con HLS}

Per lo streaming video, PeerTube utilizza il protocollo HTTP Live Streaming (HLS), sviluppato da Apple. HLS è un protocollo di streaming adattativo che consente di trasmettere video in
diretta o on-demand su Internet. Il protocollo HLS funziona dividendo il flusso video in piccoli segmenti e trasmettendoli tramite HTTP. Questo approccio consente di adattare la qualità del video in base alla larghezza di banda disponibile, garantendo una riproduzione fluida e senza interruzioni.
\begin{itemize}
    \item Divide il video in piccoli segmenti (tipicamente di 2-10 secondi)
    \item Crea un file manifest (.m3u8) che elenca i segmenti disponibili
    \item Permette la selezione automatica della qualità in base alla connessione
    \item È compatibile con la maggior parte dei browser e dispositivi moderni
\end{itemize} \cite{rfc8216}

Per eseguire streaming video P2P, PeerTube utilizza un loader/player personalizzato. Questo loader consente di scaricare i segmenti video sia dal server web sia da altri spettatori tramite WebRTC, riducendo così il carico sui server e distribuendo la banda attraverso il P2P.

\subsection{P2P Media Loader e WebRTC}

Il cuore del sistema P2P di PeerTube è costituito da:

\begin{itemize}
    \item \textbf{WebRTC}: Una tecnologia web standard per la comunicazione peer-to-peer diretta tra browser
    \item \textbf{P2P Media Loader}: Una libreria JavaScript che integra il P2P nel player video
    \item \textbf{WebTorrent Tracker}: Un tracker\footnote{Un server che aiuta a trovare altri peer nella rete BitTorrent mantenendo un elenco dei peer che stanno scaricando un determinato file.} BitTorrent per la scoperta dei peer, utilizzato come sistema di signaling
\end{itemize}

\subsubsection{WebRTC}

WebRTC \footnote{Web Real-Time Communication} è un progetto gratuito e open-source che fornisce ai browser web e alle applicazioni mobile la possibilità di instaurare comunicazioni in tempo reale tramite API standard, tipicamente in JavaScript.

Consente la comunicazione e lo streaming audio-video direttamente all'interno delle pagine web, permettendo la connessione peer-to-peer senza la necessità di installare plugin o scaricare applicazioni native.

I maggiori componenti che costituiscono WebRTC sono:
\begin{itemize}
    \item \textbf{getUserMedia}: API che consente l'accesso alla fotocamera e al microfono del dispositivo.
    \item \textbf{RTCPeerConnection}: API che consente la comunicazione peer-to-peer per lo scambio di audio, video e dati. Gestisce l'elaborazione del segnale, la gestione dei codec, la comunicazione peer-to-peer, la sicurezza e l'ottimizzazione della larghezza di banda.
    \item \textbf{RTCDataChannel}: API che consente comunicazione bidirezionale di dati arbitrari tra peer. Utilizza le stesse API di WebSocket e offre una latenza molto bassa.
\end{itemize}

Affinché un'app WebRTC possa avviare una sessione, i suoi client devono scambiarsi le seguenti informazioni:
\begin{itemize}
    \item Messaggi di controllo della sessione, utilizzati per aprire o chiudere la comunicazione.
    \item Messaggi di errore.
    \item Metadati dei media, come codec, impostazioni dei codec, larghezza di banda e tipi di media.
    \item Chiavi di sicurezza necessarie per stabilire connessioni sicure.
    \item Dati di rete, come l'indirizzo IP e la porta dell'host visibili dall'esterno.
\end{itemize}

Questo processo di signaling, ovvero la scoperta dei peer con cui connettersi e la determinazione delle modalità di stabilimento delle connessioni, richiede un meccanismo che permetta ai client di scambiarsi messaggi avanti e indietro.

L' WebRTC non include meccanismo. Questo compito è lasciato all'applicazione, che può utilizzare qualsiasi mezzo di comunicazione per lo scambio di informazioni di segnalazione.

I metodi e i protocolli di signaling da implementare sono invece definiti dal JavaScript Session Establishment Protocol (JSEP), per evitare ridondanze e massimizzare la compatibilità con le tecnologie esistenti.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/jsep-architecture-diagram_856.png}
    \caption{Architettura JSEP.}
\end{figure}

JSEP richiede lo scambio tra peer di offerte e risposte, includendo i metadati dei media da voler condividere.

\subsubsection{P2P Media Loader}

P2P Media Loader è una libreria JavaScript open-source che sfrutta le funzionalità dei browser moderni (HTML5 video e WebRTC) per distribuire contenuti multimediali tramite P2P e riprodurli attraverso l'integrazione con molti lettori video HTML5 popolari. Non richiede plugin o estensioni del browser per funzionare.

Requisiti del browser per P2P Media Loader:
\begin{itemize}
    \item Media Source Extensions (MSE) o Managed Media Source, necessarie per la riproduzione multimediale tramite i motori Hls.js e Shaka Player.
    \item Supporto a WebRTC Data Channels per lo scambio di dati tra peer.
    \item Server STUN, utilizzato da WebRTC per raccogliere \textit{ICE} candidates. Esistono diversi server pubblici disponibili.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/p2p-media-loader-network.CFcphAUE.png}
    \caption{Architettura di P2P Media Loader.}
\end{figure}

Il funzionamento di P2P Media Loader è il seguente:
Un browser web esegue un lettore video integrato con la libreria P2P Media Loader. Un'istanza di P2P Media Loader è chiamata peer. Molti peer formano una rete P2P.

P2P Media Loader inizia a scaricare i segmenti iniziali dei media tramite HTTP(S) dal server di origine o CDN. Questo consente di avviare la riproduzione dei video più velocemente. In caso di assenza di peer, il video viene scaricato tradizionalmente con HTTP.

Successivamente, P2P Media Loader invia i dettagli dello stream e i dettagli della sua connessione (candidati ICE) ai tracker di WebTorrent e ottiene da loro l'elenco di altri peer che stanno scaricando lo stesso stream di media.

P2P Media Loader si connette e inizia a scaricare i segmenti dei media dai peer ottenuti, nonché a condividere i segmenti già scaricati con loro.

Di tanto in tanto, peer casuali della rete scaricano nuovi segmenti tramite HTTP(S) e li condividono con gli altri tramite P2P.


\section{Signaling e NAT Traversal}

Come menzionato prima, un aspetto critico del sistema P2P è il processo di signaling e di NAT traversal che permette ai peer di scoprirsi e connettersi tra loro.

\textbf{NAT} è un metodo per mappare uno spazio di indirizzi IP in un altro, modificando le informazioni sugli indirizzi di rete nell'header IP dei pacchetti mentre sono in transito attraverso un dispositivo di routing del traffico. 

Questa tecnica è stata inizialmente utilizzata per evitare la necessità di assegnare un nuovo indirizzo a ogni host quando una rete veniva spostata o quando il provider di servizi Internet a monte veniva sostituito ma non poteva instradare lo spazio di indirizzi della rete. Con il tempo, è diventata uno strumento essenziale per la conservazione dello spazio globale degli indirizzi a causa dell'esaurimento degli indirizzi IPv4. Un singolo indirizzo IP instradabile su Internet di un gateway NAT può essere utilizzato per un'intera rete privata.

Poiché la traduzione degli indirizzi di rete modifica le informazioni sugli indirizzi IP nei pacchetti, le implementazioni NAT possono variare nel loro comportamento specifico in diversi casi di indirizzamento e nel loro impatto sul traffico di rete. I produttori di dispositivi che implementano NAT non documentano comunemente i dettagli specifici del comportamento NAT. \cite{rfc2663}

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/NAT_Concept-en.png}
    \caption{Schema NAT.}
\end{figure}

I problemi di attraversamento del NAT (NAT traversal) si verificano quando peer situati dietro NAT diversi tentano di comunicare tra loro direttamente.

Un modo per risolvere questo problema è utilizzare il port forwarding. Un'altra soluzione consiste nell'usare diverse tecniche di attraversamento del NAT.

\textbf{NAT Traversal} è il processo di superamento delle limitazioni imposte dai router NAT (Network Address Translation) che possono impedire la comunicazione diretta tra peer.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/nat-traversal.png}
    \caption{Schema NAT Traversal.}
\end{figure}

Esistono diverse tecniche di attraversamento del NAT, tra cui:
\begin{itemize}
    \item \textbf{UPnP} (Universal Plug and Play): Un protocollo di rete di vecchia data, ampiamente implementato che consente ai dispositivi di comunicare tra loro senza la necessità di configurazioni manuali.
    \item \textbf{NAT-PMP} (NAT Port Mapping Protocol): Un protocollo simile ad UPnP che consente ai dispositivi di comunicare tra loro attraverso un router NAT creato da Apple.
    \item \textbf{PCP} (Port Control Protocol): Il protocollo successore di NAT-PMP.
\end{itemize}

Un port mapping riuscito può bypassare efficacemente il NAT per la porta specificata, facilitando le connessioni dirette.

I dispositivi NAT non si comportano tutti in modo uniforme, il che porta a diversi livelli di difficoltà nell'attraversamento:

\begin{itemize}
    \item \textbf{Endpoint-Independent Mapping} (EIM): NAT `facili' che utilizzano lo stesso IP e porta pubblici per tutte le connessioni in uscita da un determinato IP e porta interni, indipendentemente dalla destinazione.
    \item \textbf{Endpoint-Dependent Mapping} (EDM): NAT `difficili' o `simmetrici' che creano mapping diversi di IP e porta pubblici in base all'indirizzo IP di destinazione e, a volte, anche alla porta di destinazione. Questo rende molto più difficile per i peer prevedere il corretto endpoint pubblico. Alcuni dispositivi NAT sono ancora più complessi e generano un mapping NAT completamente diverso per ogni destinazione contattata.
\end{itemize}

\textbf{STUN}\footnote{Session Traversal Utilities for NAT; originariamente Simple Traversal of User Datagram Protocol (UDP) through Network Address Translators} è un insieme standardizzato di metodi, incluso un protocollo di rete, per l'attraversamento dei gateway NAT nelle applicazioni di comunicazione interattiva in tempo reale, come voce, video e messaggistica.

STUN è uno strumento utilizzato da altri protocolli, come Interactive Connectivity Establishment (ICE), Session Initiation Protocol (SIP) e WebRTC. Consente ai dispositivi di rilevare la presenza di un traduttore di indirizzi di rete e di scoprire l'indirizzo IP pubblico mappato e il numero di porta assegnati dal NAT per i flussi UDP dell'applicazione verso host remoti.

Il protocollo richiede l'assistenza di un server di rete di terze parti (un server STUN) situato sul lato opposto (pubblico) del NAT, solitamente su Internet.

STUN quindi, è fondamentale per i client dietro un NAT, dato che li consente di scoprire il proprio indirizzo IP e le porte visibili esternamente, così come vengono viste da un server su Internet.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/stun-server.png}
    \caption{Schema STUN.}
\end{figure}

Quando le connessioni peer-to-peer dirette non possono essere stabilite, dei server di inoltro (relay) fungono da intermediari:
\begin{itemize}
    \item \textbf{TURN} (Traversal Using Relays around NAT): un protocollo standard in cui i client si autenticano con un server TURN, che assegna loro un indirizzo IP pubblico e una porta, inoltrando il traffico tra i peer.
\end{itemize} \cite{tailscaleTraversalWorks}

WebRTC utilizza il protocollo ICE (Interactive Connectivity Establishment) menzionato prima, per negoziare la connessione tra i peer, utilizzando server STUN e TURN per facilitare il processo.

\section{Algoritmo di selezione dei peer}

L'efficienza del sistema P2P dipende in modo cruciale dall'algoritmo utilizzato per selezionare i peer da cui scaricare i dati. PeerTube, e di conseguenza Novage P2P Media loader utilizza come menzionato prima un WebTorrent Tracker some sistema di signaling che utilizza un algoritmo del tutto simile a quello di BitTorrent dato che il protocollo funziona esattamente come il protocollo BitTorrent, ma utilizza WebRTC invece di TCP/uTP come protocollo di trasporto.

La specifica BitTorrent, versione 1.0, definisce vari algoritmi per la selezione dei peer; i peer vengono selezionati attraverso una combinazione di azioni da parte del tracker e dei singoli client.
Dalla parte del tracker:

\begin{itemize}
    \item  Quando un client invia una richiesta al tracker (announce), il tracker risponde con un elenco di peer che partecipano allo stesso torrent (o video su una pagina web nel nostro caso).
    \item Di default a, il tracker fornisce un elenco fino a 50 peer. Se sono disponibili meno peer, l'elenco sarà più piccolo.
    \item Il tracker generalmente seleziona i peer in modo casuale per la sua risposta. Tuttavia, può anche utilizzare un algoritmo di selezione dei peer personalizzato.
\end{itemize}

Una volta che un client riceve un elenco di peer dal tracker e stabilisce le connessioni, gestisce queste connessioni utilizzando un algoritmo di choking e optimistic unchoking.

Questo processo determina quali peer il client utilizzerà attivamente per scaricare e caricare i dati.

\begin{itemize}
    \item \textbf{Choking}: Un peer può fare choking (rifiutarsi di caricare dati) verso altri peer per diversi motivi, tra cui: Controllo della congestione TCP, per evitare sovraccarichi di rete; Strategia tit-for-tat, per garantire un tasso di download costante, dando priorità ai peer che condividono attivamente. Quando un peer viene `strangolato', il client non deve inviare richieste per blocchi di dati a quel peer.
    \item \textbf{Unchoking}: Per gestire i download e contraccambiare i peer utili, un client solitamente sblocca i quattro peer interessati che hanno il miglior tasso di upload. Questi vengono chiamati `downloaders'. Se un peer ha un tasso di upload migliore ma non è interessato, potrebbe comunque essere sbloccato, e se diventa interessato, il downloader con il tasso di upload peggiore viene bloccato. I client con un file completo utilizzano il loro tasso di upload per decidere quali peer sbloccare.
    \item \textbf{Optimistic unchoking}: Per scoprire potenziali peer migliori, il client sblocca in modo ottimistico un peer per un intervallo di 30 secondi, indipendentemente dal suo tasso di upload. Il peer sbloccato ottimisticamente ruota, il che significa che i peer appena connessi hanno una maggiore probabilità di essere scelti inizialmente.
    \item \textbf{Anti-snubbing}: Se un client smette di ricevere dati da un peer per più di un minuto, suppone di essere stato `snobbato'  e potrebbe temporaneamente smettere di caricare dati verso quel peer. Questo può portare a più di un meccanismo di unchoking ottimistico concorrente per trovare dei peer migliori.
\end{itemize} \cite{theoryBitTorrentSpecificationTheoryOrg} \cite{rfc5389}

\section{Sistema di monitoraggio integrato con OpenTelemetry}

OpenTelemetry è un framework e un toolkit open-source per l'osservabilità. Standardizza la generazione, l'esportazione e la raccolta di dati di telemetria, come tracce, metriche e log, ed è progettato per essere indipendente dai fornitori e dagli strumenti stessi.
Affronta la sfida delle pratiche di osservabilità frammentate tra diversi linguaggi, infrastrutture e fornitori, offrendo un unico set di API, specifiche e strumenti per l'istrumentazióne. Questo elimina così il \textit{vendor lock-in} e la necessità di adattarsi a più sistemi proprietari.\cite{opentelemetryWhatOpenTelemetry}

PeerTube integra OpenTelemetry, per il monitoraggio delle prestazioni complessive del server, raccogliendo metriche come:

\begin{itemize}
    \item \textbf{Percentuale di dati condivisi via P2P e HTTP}
    \item \textbf{Numero di utenti connessi}
    \item \textbf{Utilizzo della CPU, della memoria etc.}
    \item \textbf{Utilizzo della banda del server}
    \item \textbf{Errori e disconnessioni}
\end{itemize}

Queste metriche possono essere poi visualizzate attraverso dashboard Grafana o altri sistemi di monitoraggio compatibili con OpenTelemetry.

\chapter{Verifica empirica delle prestazioni P2P di PeerTube}

A dicembre 2023, il team di PeerTube ha pubblicato un articolo in cui va ad analizzarne le prestazioni facendo degli \textit{stress test} per verificare se la tecnologia P2P integrata nel sistema sia effettivamente in grado di ridurre il carico sui server con circa 1000 utenti connessi contemporaneamente, in quanto, secondo i dati raccolti da Twitch nel 2022, coprivano il 99\% dei casi di utilizzo della piattaforma.

\

Per realizzare test veritieri, il team ha simulato 1.000 spettatori simultanei utilizzando 1.000 browser Chrome, ciascuno con un indirizzo IP pubblico IPv6 dedicato. Questo è stato realizzato tramite Selenium grid, un software di automazione e testing per i browser, affiancato da Docker su cloud Hetzner e successivamente con un potente server fornito da Octopuce.

La scelta di 1.000 spettatori è significativa poiché copre la stragrande maggioranza delle dirette streaming su piattaforme importanti come Twitch, suggerendo che PeerTube può essere adeguato per un'ampia gamma di casi d'uso.
In condizioni ottimali, l'aspetto P2P di PeerTube dovrebbe ridurre la larghezza di banda necessaria per trasmettere un video in diretta di un fattore da 3 a 4, stando quanto detto degli sviluppatori di PeerTube.

\

Sono stati condotti 4 scenari di test principali:
\begin{itemize}
    \item Live streaming con impostazione \textit{Normal Latency}
    \item Live streaming con impostazione \textit{High Latency}
    \item Live streaming con impostazione \textit{High Latency} e 50\% dei peer con P2P disabilitato
    \item Un normale video \textit{on-demand}
\end{itemize}

su una macchina virtuale con:
\begin{itemize}
    \item 4 vCore i7-8700 CPU @ 3.20GHz
    \item 4 GB di RAM
    \item 1 Gbps di banda
\end{itemize}

I dati dei test sono stati raccolti tramite OpenTelemetry e Grafana, con metriche come:
\begin{itemize}
    \item Percentuale di dati trasferiti via P2P vs. dal server
    \item Utilizzo di CPU
    \item Comportamento in condizioni di rete variabili
    \item Numero di spettatori
\end{itemize}

con i quali, infine, sono stati in grado di dimostrare che PeerTube è in grado di gestire 1.000 spettatori simultanei con un carico minimo sui server, grazie alla tecnologia P2P integrata in quanto la quantità di dati trasferiti via P2P, è progressivamente aumentata con il tempo, fino a raggiungere un rapporto del 75\% dei dati totali trasferiti per i video in diretta e del 98\% per i video \textit{on-demand}.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/chrome_Mqt9TamrBT.png}
    \caption{PeerTube conclusioni sullo stress test.}
\end{figure}

Tuttavia, l'articolo non fornisce dettagli sufficienti sulla metodologia utilizzata né rilascia gli strumenti specifici per riprodurre i test in modo indipendente. \cite{joinpeertubePeerTubeStress}

\

Perciò abbiamo deciso di creare un sistema di test automatizzato che possa riprodurre i test descritti nell'articolo originale.

\section{Metodologia per la verifica empirica}

Per verificare le affermazioni degli sviluppatori di PeerTube, abbiamo deciso di:

\begin{itemize}
    \item Creare un'automazione per riprodurre indipendentemente i test descritti nell'articolo
    \item Raccogliere metriche più dettagliate rispetto a quelle presentate nell'articolo originale
    \item Analizzare i dati raccolti per valutare le prestazioni del sistema P2P di PeerTube
\end{itemize}

\section{Stack tecnologico per i test}

Per i nostri test abbiamo utilizzato una combinazione di tecnologie open source per creare un sistema di test automatizzato che sfrutta le seguenti tecnologie:

\begin{itemize}
    \item \textbf{Docker}: Per creare ambienti isolati e facilmente riproducibili
    \item \textbf{Telegraf}: Per la raccolta di metriche di sistema e di rete
    \item \textbf{MongoDB}: Per l'archiviazione strutturata dei dati raccolti
    \item \textbf{Python}: Come linguaggio principale per l'automazione
    \item \textbf{Selenium}: Per simulare browser reali che guardano lo stream
    \item \textbf{WebRTC Internals Exporter}: Una estensione del browser creata per raccogliere metriche dettagliate sulle connessioni WebRTC
    \item \textbf{WebPack}: Un sistema di compilazione e gestione delle dipendenze per il frontend web
    \item \textbf{Hetzner Cloud e script CLI}: Per distribuire i test su macchine virtuali in diverse regioni geografiche
\end{itemize}

\subsection{Docker}

Docker è una piattaforma open source che semplifica la creazione, la distribuzione e l'esecuzione di applicazioni in contenitori. I contenitori Docker sono degli ambienti isolati che simulano un sistema operativo completo, come le macchine virtuali, consentendo di eseguire applicazioni in modo consistente su qualsiasi ambiente.

La differenza tra docker e una macchina virtuale è che i container Docker condividono il kernel del sistema operativo host, riducendo l'overhead e migliorando le prestazioni, senza dover ricorrere ad un \footnote{Hypervisor: Software che consente di eseguire più sistemi operativi su singolo hardware.}\textit{Hypervisor} per la virtualizzazione.

\begin{figure}[H]
    \centering
    \includegraphics[width=350pt]{images/docker-engine.png}
    \caption{Docker Engine.}
\end{figure}

In se Docker è composto da 4 componenti principali:
\begin{itemize}
    \item \textbf{Docker Engine}: Il core del sistema, responsabile della creazione e gestione dei container nonché il processo demone eseguito sulla macchina host. Fornisce l'accesso a tutte le funzionalità e i
    servizi messi a disposizione da Docker. Mette a disposizione un insieme di comandi per la gestione dei container, delle immagini e dei volumi.
    \item \textbf{Docker Client}: Interfaccia da riga di comando e \footnote{API: sinonimo di Application Programming Interface.} \textit{API} per interagire con Docker Engine. 
    \item \textbf{Docker Image}: Un \textit{template} di sola lettura che contiene e definisce i parametri di una applicazione da eseguire in un container a runtime. Le immagini vengono create e organizzate per livelli \textit{stateless} e immutabili. 
    \item \textbf{Docker Container}: Un'istanza in esecuzione di un'immagine Docker. Un container è un ambiente isolato che esegue un'applicazione specifica e include tutto il necessario per eseguire l'applicazione, come il codice, le librerie, le variabili d'ambiente e le dipendenze. Il \textit{filesystem} del container è l'ultimo livello che viene aggiunto al quale vi è possibile accedere sia in lettura che in scrittura. I contenitori, inoltre, possono essere associati a dei volumi per la persistenza dei dati, i quali forniscono un metodo semplice e immediato per condividere dati tra i container e l'host.\\La comunicazione tra container avviene tramite la creazione di \textit{network} o reti separate che vengono connesse ai singoli container, abilitando così una sorta di LAN interna tra un insieme di container. Per far, invece, comunicare i container con il mondo esterno bisogna invece utilizzare i `port mapping' tra una porta della macchina host e una porta del container.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=200pt]{images/0_ukWqRD74ltfb5Uaz.png}
    \caption{Docker Overview.}
\end{figure}

Approfondendo il discorso del networking, Docker mette a disposizione vari tipi di reti per la comunicazione tra container, i 3 principali sono:
\begin{itemize}
    \item \textbf{Bridge}: È la rete di default che viene creata quando si installa Docker. I container connessi a questa rete possono comunicare tra loro e con il host, ma non possono comunicare con i container in altre reti.
    \item \textbf{Host}: I container connessi a questa rete, condividono la rete dell'host, quindi non hanno bisogno di fare \textit{port mapping} per comunicare con il mondo esterno.
    \item \textbf{None}: I container connessi a questa rete non hanno accesso ad alcuna rete, quindi non possono comunicare con altri container o con l'esterno.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/Docker-network-1.png}
    \caption{Docker Networking.}
\end{figure}
\cite{AzureFunctions} \cite{geeksforgeeksContainerizationUsing} \cite{geeksforgeeksDockerNetworking}

\subsection{Telegraf}

Telegraf è un agente di raccolta di metriche open source sviluppato da InfluxData. È progettato per raccogliere, elaborare e inviare metriche da una varietà di sorgenti, tra cui sistemi operativi, database, applicazioni e dispositivi di rete.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/telegraf-architecture-diagram.png}
    \caption{Architettura Telegraf.}
\end{figure}

Scritto in \textit{Go}, Telegraf è dotato di oltre 300 plugin di input, trasformazione e output di dati, che consentono di raccogliere metriche da una vasta gamma di sorgenti. Per sua natura, funziona come un pipeline di dati che può essere instradata attraverso diversi plugin per elaborare e aggregare le informazioni prima di raggiungere l'output finale.

Alcuni componenti principali di Telegraf includono:
\begin{itemize}
    \item \textbf{Agent}: Il core del sistema, responsabile della raccolta e dell'elaborazione delle metriche dai plugin di input definiti e le invia ai plugin di output specificati, in base alla configurazione fornita.
    \item \textbf{Input Plugins}: Raccolgono metriche da sorgenti come sistemi operativi, database, applicazioni e dispositivi di rete.
    \item \textbf{Processor Plugins}: Elaborano e trasformano le metriche raccolte prima di inviarle all'output.
    \item \textbf{Output Plugins}: Inoltrano le metriche elaborate a un sistema di monitoraggio o di archiviazione.
    \item \textbf{Aggregator Plugins}: Aggregano le metriche raccolte per ridurre il volume dei dati.
\end{itemize}

La configurazione di Telegraf è definita da un file di configurazione \textit{TOML} che definisce i plugin di input, processore e output da utilizzare, insieme a eventuali parametri aggiuntivi necessari per la raccolta e l'elaborazione delle metriche.

Viene spesso utilizzato affianco ad un database di tipo \textit{time-series} come InfluxDB per l'archiviazione e la visualizzazione delle metriche raccolte, ma può essere integrato con una vasta gamma di sistemi di monitoraggio e analisi dei dati.\\
Una metrica \textit{time-series} è una serie di dati indicizzati in sequenza rispetto al tempo. Un esempio è una sequenza di osservazioni o rilevazioni registrate allo scorrere del tempo. Vi sono due macrocategorie di \textit{time-series}:
\begin{itemize}
    \item \textbf{univariate time series}: le osservazioni sono monodimensionali, ovvero: viene registrato un solo valore numerico allo scorrere del tempo.
    \item \textbf{multivariate time series}: le osservazioni sono multidimensionali, ovvero, si registrano più valori numerici per un singolo istante di tempo.
\end{itemize}
Tipicamente, vengono viene rappresentate con una struttura dati che registri un timestamp, che può essere di qualche tipo specifico per date, oppure un intero, contenente uno \textit{Unix timestamp}; oltre a questo contiene dati addizionali, che nella versione più semplice possono essere un unico valore numerico, ovvero l’osservazione registrata allo scorrere del tempo.
\cite{githubGitHubInfluxdatatelegraf} \cite{noauthor_telegraf_nodate} \cite{aiknowTimeSeries}

\subsection{MongoDB}

MongoDB è un database \textit{NoSQL} open source, orientato ai documenti, sviluppato da MongoDB Inc. È progettato per essere flessibile, scalabile e ad alte prestazioni, consentendo di memorizzare e interrogare dati in modo efficiente.
Combina la capacità di scalare orizzontalmente con funzionalità come indici secondari, query per intervallo, ordinamento, aggregazioni e indici geospaziali.

Un database orientato ai documenti sostituisce il concetto di `riga' con un modello più flessibile, il `documento'. Grazie alla possibilità di includere documenti incorporati e array, l’approccio orientato ai documenti permette di rappresentare relazioni gerarchiche complesse all'interno di un singolo record.
Non ci sono schemi predefiniti: le chiavi e i valori di un documento non hanno tipi o dimensioni fisse. L'assenza di uno schema rigido rende più semplice aggiungere o rimuovere campi secondo necessità. In generale, questo accelera lo sviluppo, permettendo agli sviluppatori di iterare rapidamente e sperimentare con facilità rendendo possibile testare diversi modelli di dati e scegliere quello più adatto alle proprie esigenze.

MongoDB è progettato per essere un database generi co, quindi, oltre alle operazioni di inserimento, lettura, aggiornamento e eliminazione dei dati (\textit{CRUD}), offre alcune funzionalità uniche in più, tra cui:
\begin{itemize}
    \item \textbf{Indicizzazioni}: Indici di diversi tipi, tra cui indici singoli, composti, geospaziali e testuali. Gli indici possono essere creati per qualsiasi campo all'interno di un documento, consentendo di ottimizzare le query per le prestazioni.
    \item \textbf{Aggregazioni}: Un'ampia gamma di operazioni di aggregazione, come \textit{group}, \textit{match}, \textit{project} e \textit{sort}, che consentono di eseguire query complesse e analisi dei dati direttamente nel database.
    \item \textbf{Collezioni speciali}: Collezioni speciali come le collezioni\textit{time-series} e le collezioni \textit{time-to-live}, che semplificano la gestione di dati temporali e di dati che devono essere eliminati dopo un certo periodo di tempo come ad esempio le sessioni utente.
\end{itemize}

MongoDB memorizza i record di dati come documenti (nello specifico documenti \textit{BSON}, ovvero una rappresentazione binaria di documenti in formato \textit{JSON}), che sono raggruppati in collezioni. Un database contiene una o più collezioni di documenti.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/crud-annotated-document.png}
    \caption{Documento JSON.}
\end{figure}

\textit{JSON}, o JavaScript Object Notation, è un formato di scambio dati testuale, basato su una sintassi di oggetti JavaScript. È comunemente utilizzato per trasmettere dati strutturati su una rete, come ad esempio tra un server e un client web. Un \textit{documento JSON}, invece, è una collezione di campi e valori organizzata in un formato strutturato.

MongoDB Query Language, o \textit{MQL}, è il linguaggio di query utilizzato per interagire con un database MongoDB. MQL è simile a SQL, ma è progettato per lavorare con documenti JSON e collezioni di documenti, piuttosto che con tabelle e righe. Consente agli utenti di recuperare documenti che corrispondono a criteri specifici, eseguire aggregazioni, apportare aggiornamenti ai documenti ed effettuare cancellazioni di documenti. La sintassi di MQL è progettata per essere semplice e intuitiva. Permette agli utenti di specificare condizioni utilizzando operatori come \$eq (uguale), \$ne (diverso), \$gt (maggiore di), \$lt (minore di) e molti altri. È possibile anche utilizzare operatori `bitwise' come \$and, \$or e \$not per creare query complesse.

\begin{figure}[H]
    \centering
    \includegraphics[width=280pt]{images/mongodb-pipelines.png}
    \caption{MongoDB Aggregation Pipeline.}
\end{figure}

Infine, il MongoDB Query Language Aggregation Framework, è un set di processi che trasforma i dati in strutture che possono essere utilizzate per l'analisi. L'aggregazione si basa su un concetto di \textit{pipeline}, in cui i documenti vengono passati attraverso una serie di fasi di trasformazione. Ogni fase della pipeline esegue un'operazione specifica sui documenti, come filtering, proiezione, ordinamento, raggruppamento e altro ancora. Le fasi della pipeline, possono essere quindi concatenate per creare query più complesse.\cite{10.5555/2544030} \cite{mongodbDocumentsMongoDB} \cite{knowiBestIntroduction}

\subsection{Python}

Python è un linguaggio di programmazione ad alto livello, interpretato, orientato agli oggetti e con semantica dinamica. È progettato per essere facile da leggere e scrivere, con una sintassi pulita e chiara che favorisce la leggibilità del codice. Python è noto per la sua facilità d'uso e la sua versatilità, che lo rendono adatto a una vasta gamma di applicazioni, dallo sviluppo web alla data science, all'automazione dei processi.

Essendo un linguaggio interpretato, Python non richiede una fase di compilazione, ma viene eseguito direttamente da un \textit{interpreter}. Questo lo rende particolarmente adatto per lo sviluppo rapido di applicazioni e per l'iterazione veloce durante lo sviluppo. Python è anche noto per la sua vasta libreria standard, che fornisce un'ampia gamma di moduli e pacchetti pronti all'uso per svolgere una varietà di compiti comuni e per questo viene utilizzato spesso per fare `data science'.\cite{10.5555/1593511}

L'indentazione è parte fondamentale in quanto, a differenza di altri linguaggi di programmazione dove l'indentazione è solo una convenzione, in Python è obbligatoria e definisce la struttura del codice. Questo rende il codice più leggibile e coerente, ma richiede anche attenzione per mantenere una corretta struttura del codice.

\break

\lstset{language=Python}
\begin{lstlisting}[caption={Esempio di codice Python}, captionpos=b,  basicstyle=\footnotesize]
    import numpy as np
        
    def incmatrix(genl1,genl2):
        m = len(genl1)
        n = len(genl2)
        M = None #to become the incidence matrix
        VT = np.zeros((n*m,1), int)  #dummy variable
        
        #compute the bitwise xor matrix
        M1 = bitxormatrix(genl1)
        M2 = np.triu(bitxormatrix(genl2),1) 
    
        for i in range(m-1):
            for j in range(i+1, m):
                [r,c] = np.where(M2 == M1[i,j])
                for k in range(len(r)):
                    VT[(i)*n + r[k]] = 1;
                    VT[(i)*n + c[k]] = 1;
                    VT[(j)*n + r[k]] = 1;
                    VT[(j)*n + c[k]] = 1;
                    
                    if M is None:
                        M = np.copy(VT)
                    else:
                        M = np.concatenate((M, VT), 1)
                    
                    VT = np.zeros((n*m,1), int)
        
        return M
\end{lstlisting}

\subsection{Selenium}

Selenium è un framework open-source ampiamente utilizzato per l'automazione dei browser web. Fornisce un insieme di strumenti e librerie che consentono a tester e sviluppatori di interagire con gli elementi di una pagina, simulare azioni dell'utente ed eseguire test automatizzati su applicazioni web.

Uno degli aspetti chiave di Selenium è la sua capacità di funzionare con diversi browser, garantendo la compatibilità cross-browser e permettendo l'esecuzione di test in ambienti differenti.

Supporta diversi browser popolari, tra cui Google Chrome, Mozilla Firefox, Microsoft Edge, Safari e Opera. Ogni browser è gestito tramite implementazioni specifiche di \textit{WebDriver}, che fungono da ponte tra Selenium e il browser.

\begin{figure}[H]
    \centering
    \includegraphics[width=350pt]{images/which-browser-supports-selenium-1.png}
    \caption{Browser supportati da Selenium.}
\end{figure}

Utilizzando i WebDriver, sviluppatori e tester possono scrivere script di automazione nel loro linguaggio di programmazione preferito ed eseguirli su diversi browser. Selenium WebDriver offre un'API unificata che astrae le differenze tra i vari browser, consentendo un'automazione fluida e risultati di test coerenti.

Una volta costruiti i casi di test, i dati devono essere comunicati al driver del browser in qualche modo. In Selenium, questo avviene utilizzando il `JSON Wire Protocol' con HTTP come gestore della comunicazione.

Poiché la comunicazione avviene in un'infrastruttura client-server, nel mondo di Selenium WebDriver questo sistema è noto come \textit{request-response} o \textit{command-response}.

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/JSON-Wire-Protocol-over-HTTP-Client.png}
    \caption{JSON Wire Protocol.}
\end{figure}

Il funzionamento dei WebDriver può essere riassunto in alcuni passaggi chiave:

\begin{itemize}
    \item Un tester scrive uno script di test automatizzato destinato a un driver di browser specifico.
    \item Quando viene premuto il pulsante `Esegui', lo script viene convertito in formato API con dati in JSON.
    \item I dati vengono trasferiti al driver del browser utilizzando il JSON Wire Protocol su una rete HTTP come API RESTful.
    \item Il driver del browser riceve i dati e, se la validazione ha successo, comunica le azioni al browser tramite HTTP.
    \item Se la validazione fallisce, gli errori vengono restituiti al client.
    \item Una volta avviato il browser, il driver esegue le azioni una per una, simulando il comportamento di un tester manuale attraverso l'automazione.
    \item I comandi vengono inviati tramite HTTP, e le risposte vengono ricevute dallo stesso protocollo nel driver.
    \item Dopo l'esecuzione di tutte le azioni, il browser si chiude e il driver comunica i risultati al client.
\end{itemize}

Affinché il driver possa comunicare correttamente con il browser, è fondamentale che il browser stesso sia installato sul sistema, e che il sistema e il suo ambiente sia configurato correttamente, con tutti i prerequisiti necessari per l'esecuzione dei test.

Un altro componente messo a disposizione da Selenium è, \textit{Selenium Grid}, che permette di eseguire test su più macchine e browser remoti contemporaneamente, riducendo i tempi di esecuzione e migliorando l'efficienza dei test, instradando i comandi inviati dal client alle istanze remote dei browser ed è composto da 2 componenti principali:

\begin{itemize}
    \item \textbf{Hub}: Il server principale che funge da punto di ingresso per i test. Riceve i comandi dai client e li instrada alle istanze dei browser remote.
    \item \textbf{Node}: Le macchine remote che eseguono i test. Si connettono al \textit{Hub} e ricevono i comandi per eseguire i test sui browser installati.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/selenium-grid.jpg}
    \caption{Architettura Selenium Grid.}
\end{figure}

Per fare tutto questo, Selenium mette a disposizione varie immagini Docker preconfigurate con tutto il necessario per eseguire i test, come il browser, il driver, l'hub, e le dipendenze necessarie, con anche diverse versioni legacy per testare la compatibilità con versioni obsolete.

In particolare, a noi interessa l'immagine \textit{selenium/standalone-chrome}, che contiene tutto il necessario per eseguire test su Chromium, incluso il browser stesso, il driver e il server Selenium, ed è stata usata come base per \textbf{creare una immagine Docker monolitica} per i nostri test, che include tutte le ulteriori dipendenze necessarie come:
\begin{itemize}
    \item \textbf{Python}: Per l'automazione.
    \item \textbf{Telegraf}: Per la raccolta ed invidio di tutte le metriche.
    \item \textbf{WebRTC Internals Exporter}: Per la raccolta delle metriche WebRTC.
    \item \textbf{Webpack}: Per la sostituzione delle variabili d'ambiente nel codice JavaScript.
\end{itemize} \cite{TestGrid_2024} \cite{scalerWhichBrowser} \cite{seleniumSeleniumBrowser}

\subsection{WebRTC Internals Exporter}

WebRTC Internals Exporter è un'estensione per Chromium che consente di esportare le metriche WebRTC da un browser in un formato leggibile e analizzabile. Creato da un ricercatore Italiano, è stato progettato per semplificare il processo di raccolta e analisi delle metriche WebRTC, che altrimenti sarebbero difficili da ottenere in quanto Chromium mette a disposizione uno strumento chiamato WebRTC-internals, che consente di visualizzare le statistiche WebRTC in tempo reale, ma non offre un modo semplice per esportarle dato che di base offre solo la creazione di file `dumps' non automatizzabile.

L'uso di webrtc-internals con il processo di creazione/caricamento dei dump presenta alcune grosse limitazioni:

\begin{itemize}
    \item È necessario aprire la pagina \textit{chrome://webrtc-internals} prima di avviare una sessione. Se la sessione è già in corso e si verificano problemi, non è possibile raccogliere metriche retroattivamente.
    \item La visualizzazione delle metriche è limitata nel tempo e non è possibile personalizzarle, filtrarle o creare query aggiuntive sui dati raccolti.
    \item L'uso di file dump può rendere difficile l'archiviazione e l'organizzazione dei dati dei test, oltre alla condivisione dei risultati. Inoltre, il caricamento di file dump di grandi dimensioni in altri strumenti di analisi, potrebbe richiedere molto tempo e memoria.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=300pt]{images/web-rtc-internals-chrome.png}
    \caption{Grafici WebRTC Internals.}
\end{figure}

WebRTC Internals Exporter risolve questi problemi abilitando l'esportazione delle metriche verso un servizio chiamato \textit{Prometheus PushGateway}.
Prometheus PushGateway è un servizio progettato per permettere a lavori effimeri e batch di esporre le proprie metriche a Prometheus. Poiché questi processi potrebbero non esistere abbastanza a lungo da essere interrogati direttamente, possono invece inviare le loro metriche al PushGateway, garantendo così la raccolta dei dati.

Tecnicamente l'estensione funziona in questo modo: viene pre-caricato un codice JavaScript che sovrascrive la classe globale \textit{RTCPeerConnection}.

La nuova classe assegna un ID casuale a tutti gli oggetti peer connection creati e li memorizza all'interno dell'oggetto \textit{webrtcInternalExporter}. L'utente può abilitare l'estensione per la scheda attualmente aperta facendo clic sull'icona dell'estensione e attivando la relativa checkbox.

Dopo l'attivazione, lo script di override inizierà a chiamare periodicamente il metodo \textit{getStats} sugli oggetti creati. Tutte le metriche selezionate verranno inviate allo script in background, che le inoltrerà al servizio PushGateway configurato.

Il metodo \textit{getStats} è un metodo standardizzato definito nell'API WebRTC che consente di ottenere le statistiche relative a una connessione peer-to-peer.\cite{WebRTCDebugging}

\

Questo progetto fa uso di una \footnote{Disponibile qui: \url{https://gitlab.di.unimi.it/mirko.milovanovic/peertube-collector/-/tree/main/webrtc-internals-exporter}} \textbf{versione altamente modificata} di WebRTC Internals Exporter, per adattarsi alle nostre esigenze di test e automazione. In particolare, abbiamo modificato le funzionalità:

\begin{itemize}
    \item Abilitare l'esportazione delle metriche WebRTC verso un \textit{endpoint HTTP RESTful} al posto di Prometheus PushGateway, con una formattazione dei dati personalizzata, ma sempre basata su JSON.
    \item Aggiunta di metriche esportate aggiuntive rispetto a quelle di base fornite da \textit{getStats}.
    \item Abilitazione automatica dell'estensione all'avvio del browser, senza intervento manuale.
    \item Supporto alla configurazione tramite variabili d'ambiente per semplificare l'integrazione con il nostro sistema di test.
\end{itemize}

\newpage
\lstset{language=json}
\begin{lstlisting}[caption={Esempio di dati JSON con le metriche esportate da WebRTC Internals Exporter}, captionpos=b,  basicstyle=\scriptsize]
    {
        "_id": "67cf2a286904313f4e5ad32c",
        "player": {
            "Codecs": {
                "Audio": "mp4a.40.2",
                "Video": "avc1.64002a"
            },
            "Connection Speed": {
                "Granularity": "s",
                "Speed": 16777216
            },
            "Download Breakdown": {
                "Peers": 0,
                "Server": 11534336
            },
            "Live Latency": {
                "Edge": 0,
                "Latency": 21
            },
            "Network Activity": {
                "Down": 7340032,
                "Up": 0
            },
            "P2P": "enabled",
            "Player mode": "p2p-media-loader",
            "Resolution": "1080p",
            "Total Transfered": {
                "Down": 11534336,
                "Up": 0
            },
            "Video UUID": "70663bee-df65-4080-84bb-eefc5a11ab75",
            ...
        },
        "peers": [
            {
                "connectionState": "new",
                "iceCandidateErrors": [
                    {
                        "errorCode": 701,
                        "errorText": "STUN host lookup received error.",
                        "timestamp": 1741629977060,
                        "url": "stun:stunserver2024.stunprotocol.org:3478"
                    },
                    ...
                ],
                "iceCandidates": [
                    {
                        "candidate": "candidate: 3130924284 1 udp 2113937151 172.17.0.2 43668...",
                        "component": "rtp",
                        "foundation": "3130924284",
                        "port": 43668,
                        "priority": 2113937151,
                        "protocol": "udp",
                        "relatedAddress": null,
                        "relatedPort": null,
                        "sdpMLineIndex": 0,
                        "sdpMid": "0",
                        "tcpType": null,
                        "timestamp": 1741629977042,
                        "type": "host",
                        "usernameFragment": "6V/z"
                    },
                    ...
                ],
                "iceConnectionState": "new",
                "iceGatheringState": "complete",
                "id": "0dfd00af-518b-46c3-a2de-bc3330da9312",
                "signalingState": "have-local-offer",
                "url": "https://tube.kobim.cloud/w/eT1NZibmwMy6bx6N2YGLwr",
                "values": [
                    {
                        "bytesReceived": 0,
                        "bytesSent": 0,
                        "id": "D1",
                        "label": "01e722a46bc1440994d511d27e86171d976d105a",
                        "messagesReceived": 0,
                        "messagesSent": 0,
                        "protocol": "",
                        "state": "connecting",
                        "timestamp": 1741629979445.746,
                        "type": "data-channel"
                    },
                    ...
                ]
            }
        ],
        "tags": {
            "host": "selenium-nbg1-node-5-instance-1",
            "session": "64001538ac0eb86fafc5ed531b96ff7c",
            "url": "https://tube.kobim.cloud/w/eT1NZibmwMy6bx6N2YGLwr"
        },
        "timestamp": "2025-03-10T18:06:19.496Z"
    }
\end{lstlisting}

\subsection{Webpack}

Webpack è un bundler di moduli per applicazioni JavaScript. Prende moduli con varie dipendenze e genera dei file statici che rappresentano quei moduli. È ampiamente utilizzato per applicazioni web moderne, in particolare quelle basate su framework come React, Angular e Vue.js.

Quando Webpack elabora un'applicazione, costruisce internamente un grafo delle dipendenze a partire da uno o più entry points. Successivamente, combina tutti i moduli necessari al progetto in uno o più bundle, che sono asset statici utilizzati per servire i contenuti dell'applicazione.

Di default, Webpack `comprende' solo file JavaScript e JSON.

Per gestire altri tipi di file, utilizza i \textit{Loaders}, che permettono di elaborare e convertire vari formati (come CSS, immagini o TypeScript) in altro moduli validi. Questi moduli possono essere quindi usati dall'applicazione ed aggiunti al grafo delle dipendenze.

Altro componente essenziale sono i \textit{Plugin}. Mentre i \textit{Loaders} trasformano i file in moduli validi, i \textit{Plugin} servono per eseguire operazioni più avanzate, come ottimizzazione, gestione degli asset, variabili d’ambiente e molto altro.\cite{webpackConceptsWebpack}

\subsection{Hetzner Cloud e script CLI}

Hetzner Cloud è un servizio di cloud computing offerto da Hetzner Online GmbH, un provider di servizi di hosting e data center con sede in Germania. Hetzner Cloud offre una vasta gamma di servizi di cloud computing, tra cui server virtuali, storage, reti e servizi di sicurezza.

Sulla base di quello che è stato fatto da PeerTube, abbiamo deciso di utilizzare Hetzner Cloud per distribuire i nostri test su macchine virtuali in diverse regioni geografiche, in quanto, gli script per l'automazione dei test sono l'unica parte fornitaci da PeerTube nell'articolo originale. Anche qua abbiamo utilizzato delle versioni altamente modificate per adattarle alle nostre esigenze.

Gli script fanno utilizzo della \footnote{CLI: sinonimo di Command-line interface} \textit{CLI}, di Hetzner Cloud, che consente di gestire le risorse cloud direttamente dalla riga di comando, e sono formati da 2 parti principali: uno script per la creazione delle macchine virtuali e uno script per l'avvio dei test.

Rispetto a quelli originali, li abbiamo modificati per far utilizzo delle variabili d'ambiente per la configurazione del nostro sistema di test, e per sostituire Selenium Grid, con l'immagine Docker monolitica standalone che abbiamo creato.\cite{githubGitHubHetznercloudcli} \cite{framagitFramasoftPeerTube}

\vfill \break
\section{Architettura del sistema di test}

Finora abbiamo descritto le tecnologie utilizzate alla base per creare il nostro sistema di test, senza però piegare effettivamente come queste vengono integrate e utilizzate insieme per creare un sistema di test automatizzato.

Introduciamo quindi l'ultimo pezzo necessario per far funzionare il tutto, ovvero il \textbf{\textit{collector}}, un'applicazione Python che si occupa di fare \footnote{Il data scraping è una tecnica in cui un programma informatico estrae dati da un output leggibile dall'uomo generato da un altro programma.} scraping delle metriche di PeerTube, di raccogliere le metriche WebRTC tramite l'estensione Chromium, e di inviare il tutto a Telegraf per l'elaborazione e l'invio al database.

\vfill

\begin{figure}[h]
    \centering
    \includegraphics[width=\textwidth]{images/mermaid-diagram-2025-03-22-144148.png}
    \caption{Architettura del collector.}
    \label{fig:architettura-collector}
\end{figure}
\vfill\break

Nella figura \ref{fig:architettura-collector} viene mostrato il funzionamento e il flusso dei dati all'interno del \textit{collector} e come esso si interfacci con le altre tecnologie utilizzate.

Nello specifico il \textit{collector} è composto da 3 parti principali:

\begin{itemize}
    \item Un Python script principale che coordina il tutto
    \item Selenium
    \item WebRTC Internals Exporter
\end{itemize}

Selenium e WebRTC Internals Exporter li abbiamo già descritti in precedenza, mentre il Python script è il cuore del sistema, che si occupa di coordinare le altre componenti, di avviare e fermare i test, di raccogliere i dati, aggregarli e di inviarli a Telegraf per l'invio al database.

L'intero progetto è disponibile qui:
\begin{itemize}
    \item \url{https://gitlab.di.unimi.it/mirko.milovanovic/peertube-collector}
\end{itemize}

\subsection{Difficoltà incontrate e soluzioni}

Durante la creazione del sistema, abbiamo incontrato diverse difficoltà, per lo più sistemistiche, che hanno richiesto soluzioni creative per superarle. Alcune delle principali sfide sono state:

\begin{itemize}
    \item \textbf{Accesso agli indirizzi IP forniti da WebRTC}: WebRTC dalle ultime versioni come misura di sicurezza e privacy, non permette più l'accesso e la visualizzazione degli indirizzi IP locali delle macchine coinvolte nella connessione grazie a tecniche di offuscazione, rendendo difficile la raccolta di queste informazioni. Per ovviare a questo problema ci siamo avvalsi di 2 soluzioni: la prima consiste nell'utilizzare una versione vecchia di Chromium, nello specifico una versione anteriore o uguale alla 129.0, in quanto in queste versioni l'offuscazione è presente ma è possibile disabilitarla tramite un flag da interfaccia grafica; la seconda soluzione invece consiste proprio nel disabilitare questa funzionalità ma da riga di comando tramite un altro flag, all'avvio del browser.
    \item \textbf{Limitazioni delle API di PeerTube}: PeerTube fornisce delle API per la gestione della piattaforma, moderazione dei video, e altro ancora, ma non fornisce API per la raccolta delle metriche dei video. Alcune metriche generiche sono esposte via OpenTelemetry ma non sono specifiche per un singolo utente o video. Per ovviare a questo problema, abbiamo utilizzato il data scraping per estrarre le metriche direttamente dalla pagina web.
    \item \textbf{Gestione delle variabili d'ambiente nell'estensione Chrome}: WebRTC Internals Exporter è un'estensione per Chromium che consente di esportare le metriche WebRTC da un browser in un formato leggibile e analizzabile. Tuttavia, l'estensione non supporta la sostituzione delle variabili d'ambiente nel codice JavaScript, in quanto viene caricata ed eseguita runtime in un ambiente isolato, rendendo difficile la configurazione dinamica dell'estensione. L'utilizzo di WebPack ci consente di configurare l'estensione in fase di compilazione, sostituendo le variabili d'ambiente con i valori corretti prima di caricarla nel browser.
    \item \textbf{Raccolta dei dati dei test su macchine virtuali distribuite}: Data la distribuzione geografica delle nostre macchine virtuali di test, abbiamo dovuto affrontare la sfida di raccogliere ed aggregare i dati in modo efficiente e coordinato. Questa sfida l'abbiamo risolta utilizzando Telegraf come agente di raccolta dati su ogni VM, configurandolo per inviare le metriche ad un'istanza centrale di MongoDB. MongoDB è stato scelto per il suo supporto nativo a documenti JSON e per la capacità di gestire grandi volumi di dati time-series provenienti da fonti eterogenee.Le API di Hetzner Cloud ci hanno permesso di automatizzare il deployment e la configurazione di tutte queste componenti su macchine distribuite in diverse regioni geografiche.
\end{itemize}

\subsection{Python script}

Il funzionamento dello script è relativamente semplice; vengono eseguiti dei passaggi in successione per arrivare in una situazione in cui i dati sono costantemente raccolti e inviati al database creando quindi un ciclo infinito che si ripete ogni 2 secondi circa, fin quando il test non viene fermato.

\

Importante particolarità dello script è la possibilità di creare e caricare plugin personalizzati che permettono di estrarre metriche di vario tipo da potenzialmente qualsiasi pagina web e non solo da PeerTube. Questo potenzialmente permette di estendere il sistema di test a qualsiasi altra piattaforma di video streaming, o di qualsiasi altro tipo, semplicemente creando un plugin personalizzato.
Questa funzionalità è stata implementata utilizzando le \textit{Abstract Base Classes} di Python, che permettono di definire delle classi base che devono essere implementate dalle classi derivate, e che permettono di definire delle interfacce comuni.

\break
\lstset{language=Python}
\begin{lstlisting}[caption={Abstract Base Classes}, captionpos=b,  basicstyle=\scriptsize]
# Abstract Base Classes for Plugins
class StatsSetupPlugin(abc.ABC):
    @abc.abstractmethod
    def setup_stats(
        self,
        driver: webdriver.Remote | webdriver.Chrome,
        url: str,
        retries: int = 5
    ) -> webdriver.Remote | webdriver.Chrome:
        pass

class StatsDownloadPlugin(abc.ABC):
    @abc.abstractmethod
    def download_stats(
        self,
        driver: webdriver.Remote | webdriver.Chrome,
        peersDict: dict,
        socket_url: str,
        socket_port: int
    ):
        pass

    @staticmethod
    def saveStats(stats: list, socket_url: str, socket_port: int):
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            logger.debug(f'Saving stats: {json.dumps(stats, indent=4)}')
            sock.sendto(json.dumps(stats).encode(), (socket_url, socket_port))
            sock.close()
            logger.debug('Sent stats to socket.')
        except socket.error as e:
            logger.error(f'Got socket error: {e}')
\end{lstlisting}



Per tutto questo, alla creazione, abbiamo fatto uso di alcune librerie Python tra cui: \textit{selenium} e \textit{beautifulsoup4}.
\\ \textit{BeautifulSoup} è una libreria Python che permette di estrarre dati da file HTML e XML. È in grado di navigare nella struttura del documento, estrarre i dati, modificarli e salvare le modifiche. È spesso utilizzata per fare \textit{web scraping}. Assieme, quste due librerie, ci permettono di interagire con il browser e di estrarre i dati necessari dalla pagina web di PeerTube.\cite{10617017}

I passaggi presenti in figura \ref{fig:architettura-collector} possono essere riassunti come:

\begin{itemize}
    \item \textbf{Inizializzazione}: Viene impostata da riga di comando o tramite variabili d'ambiente la configurazione del test.
    \begin{description}
        \item Queste possono includere: I plugin personalizzati BeautifulSoup, l'URL del video da analizzare, l'URL del server Telegraf, l'URL dell'hub di Selenium Grid, il percorso dell'estensione di WebRTC Internals Exporter, e altro ancora.
    \end{description}
    \item \textbf{Avvio del browser}: Viene avviato il browser ed aperta la pagina del video specificato tramite Selenium, con l'estensione di WebRTC Internals Exporter installata ed abilitata. Viene anche avviato in ascolto un server HTTP in background per ricevere le metriche WebRTC tramite un endpoint locale POST dedicato.
    \item \textbf{Avvio del test}: Viene caricata la pagina del video e tramite Selenium viene controllato che il video sia in riproduzione tramite il controllo dell'esistenza del bottone play.
    \item \textbf{Raccolta delle metriche WebRTC}: L'estensione per WebRTC inizia a raccogliere le metriche e ogni 2 secondi circa le invia allo script principale. Viene quindi di fatto instaurato un ciclo che viene usato dallo script come sorgente di clock per la raccolta delle altre metriche.
    \item \textbf{Raccolta delle metriche video di PeerTube}: Utilizzando BeautifulSoup, vengono trasformate e raccolte le metriche del player video di PeerTube, come la qualità del video, il buffering, quantità di dati trasferiti, la latenza, e altro ancora. Il tutto viene convertito in un formato JSON.
    \item \textbf{Invio delle metriche a Telegraf}: Le metriche raccolte, vengono inviate a Telegraf tramite una socket di sistema, per l'elaborazione e l'invio al database finale, nel nostro caso MongoDB. C'è un passaggio fondamentale però che Telegraf esegue, ed è quello di fare \textit{string-join} dei dati JSON, ovvero di `appiattire' e trasformare i dati in una stringa, per poi inviarli al database. Questo viene fatto in quanto Telegraf, utilizzando il plugin di input per il formato JSON, converte gli array \textbf{in singole metriche separate}, e non come un unico documento, perdendo quindi la struttura originale dei dati. In se questo non è un problema, ma per la nostra analisi, è fondamentale mantenere la struttura originale dei dati per facilitarci il lavoro. Infine per ricavare i documenti interi, un ulteriore passaggio finale va effettuato nel database, in differita, per convertirli da stringhe ad oggetti JSON validi.
\end{itemize}

Va inoltre evidenziata la scelta di utilizzare un solo script Python per coordinare il tutto, sia l'inizializzazione che raccolta delle metriche dalle pagine web e dalla estensione esterna, in quanto questo ha semplificato la gestione e soprattutto la creazione del sistema e permette come bonus di avere un unico punto di controllo per l'intero processo.

\newpage

\begin{lstlisting}[caption={Codice del plugin per la raccolta delle metriche di PeerTube}, captionpos=b,  basicstyle=\scriptsize]
# Default Plugin Implementation
class DefaultStatsSetupPlugin(StatsSetupPlugin):
    def setup_stats(
        self, driver: webdriver.Remote, 
        url: str, 
        retries: int = 5
    ) -> webdriver.Remote:
        logger.log(logging.INFO, 'Setting up stats.')
        actions = ActionChains(driver)
        wait = WebDriverWait(driver, 30, poll_frequency=0.2)
        
        sleep(2)

        for attempt in range(retries):
            driver.get(url)
            try:
                wait.until(
                    ec.presence_of_element_located(
                        (By.CLASS_NAME, 'vjs-big-play-button')
                    )
                )
                break
            except Exception:
                logger.error(
                    f'Timeout. Attempt {attempt + 1} of {retries}'
                    )
                if attempt == retries - 1:
                    logger.error('Timeout limit reached. Exiting.')
                    driver.quit()
                    raise SystemExit(1)

        actions.click(
            driver.find_element(By.CLASS_NAME ,'video-js')
        ).perform()
        wait.until(
            ec.visibility_of_element_located((By.CLASS_NAME, 'vjs-control-bar'))
        )
        actions.context_click(
            driver.find_element(By.CLASS_NAME ,'video-js')
            .perform()
        )
        statsForNerds = driver.find_elements(
            By.CLASS_NAME ,'vjs-menu-item'
            
        actions.click(statsForNerds[-1]).perform()
        wait.until(
            ec.presence_of_element_located(
                (By.CSS_SELECTOR, 'div.vjs-stats-content[style="display: block;"]')
            )
        )
        actions.move_to_element(
            driver.find_element(By.CLASS_NAME ,'vjs-control-bar')
        ).perform()

        logger.log(logging.INFO, 'Stats setup complete.')
        
        return driver
\end{lstlisting}

\newpage

Il diagramma finale dell'architettura del nostro sistema è il seguente: 

\begin{itemize}
    \item Un server centrale che esegue un'istanza di PeerTube e che raccoglie le metriche fornite da OpenTelemetry.
    \item Molteplici macchine virtuali distribuite geograficamente sul globo che simulano gli spettatori.
    \item Una applicazione Python in esecuzione su ogni singola macchina, che coordina Selenium e Telegraf per raccogliere le statistiche del video in riproduzione e le metriche WebRTC. 
    \item Un database centralizzato per la raccolta dei dati.
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/chrome_KEAVUAGKCE.png}
    \caption{Istanza di Selenium Standalone con il collector in esecuzione.}
\end{figure}

\section{Casi d'uso e scenari di test riprodotti}

Come descritto in precedenza, abbiamo riprodotto due scenari di test principali dei 4 casi d'uso descritti nell'articolo di PeerTube per motivi di tempo e risorse. Questi sono:

\begin{itemize}
    \item Live streaming con impostazione \textit{Normal Latency}: Il setup standard di PeerTube
    \item Live streaming con impostazione \textit{High Latency}: La configurazione che privilegia il P2P a scapito della latenza
\end{itemize}

Per ciascun scenario, abbiamo impostato il numero di client a 5 (limite di Hetzner Cloud), distribuiti per il globo, e raccolto le seguenti statistiche:

\begin{itemize}
    \item Statistiche del player web (risoluzione, bitrate, buffering, latenza, ecc.)
    \item Statistiche WebRTC (peer connection, ICE candidates, ICE connection state, ecc.)
    \item Informazioni identificative dei singoli peer (url del video, ID sessione, ID peer)
    \item Timestamp di raccolta
\end{itemize}

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/hetzner-cloud-datacenters.png}
    \caption{Distribuzione geografica delle macchine virtuali Hetzner Cloud.}
\end{figure}

\chapter{Conclusioni}

\section{Risultati e analisi}

Attraverso il nostro sistema di test automatizzato, siamo riusciti a raccogliere i dati che ci hanno permesso di analizzare le prestazioni del sistema P2P di PeerTube. I risultati principali confermano molte delle affermazioni fatte dagli sviluppatori nella loro pubblicazione originale.

I nostri dati raccolti arrivano da più fonti differenti; per verificare le affermazioni originali, ci siamo avvalsi nell'utilizzare sia i dati raccolti dal sistema di monitoraggio interno di PeerTube (ovver OpenTelemetry), sia i dati raccolti tramite il nostro sistema di test automatizzato esterno ed indipendente. Questo ci ha permesso di avere una visione più completa e dettagliata delle prestazioni del sistema P2P e soprattuto permette la verifica di soluzioni diverse che non includono un sistema di monitoraggio interno.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/grafana-default-latency.png}
    \caption{Grafico nel tempo del traffico HTTP e P2P per la configurazione Normal Latency raccolto da Grafana/OpenTelemetry.}
    \label{fig:normal-latency-grafana}
\end{figure}

Nella figura \ref{fig:normal-latency-grafana} sono mostrati i grafici del traffico HTTP e P2P nel tempo raccolti da automaticamente da OpenTelemetry per la configurazione Normal Latency. Come si evidenzia, il traffico P2P totale è nettamente superiore al traffico HTTP, con un rapporto di circa 3:1.

Questo viene ulteriormente confermato dai nostri dati raccolti esternamente da Selenium sulle statistiche messe a disposizione dal player video, che mostrano un traffico P2P che raggiunge il 75\% del traffico totale in download. Questo è un risultato molto positivo, in quanto dimostra che il sistema P2P di PeerTube è in grado di ridurre significativamente il carico sui server centrali, permettendo una distribuzione più efficiente dei contenuti video.

\begin{table}[H]
\centering
\caption{Traffico totale in download per la configurazione Normal Latency.}
\label{tab:network-traffic}
\begin{tabular}{lrr}
\toprule
\textbf{Metrica} & \textbf{Valore} & \textbf{Percentuale} \\
\midrule
Download totale da peer & 8.10 GiB & 75\% \\
Download totale da server & 2.75 GiB & 25\% \\
Download totale & 10.86 GiB & 100\% \\
\midrule
Rapporto P2P/Server & 3:1 & \\
\bottomrule
\end{tabular}
\end{table}

I valori non sono strettamente identici a quelli mostrati in figura \ref{fig:normal-latency-grafana} in quanto sono stati raccolti in con metodologie diverse, ma sono comunque molto vicini e confermano i risultati ottenuti.

Ulteriore conferma arriva dai valori raccolti da WebRTC e il campo \textit{data-channel}, che mostrano un traffico P2P in download totale di 8.80 GiB, leggermente maggiore rispetto a quelli forniti dal player/OpenTelemetry, ma pur sempre con un rapporto di 3:1 rispetto al traffico HTTP totale.

\begin{figure}[H]
    \centering
    \includegraphics[width=\textwidth]{images/grafana-high-latency.png}
    \caption{Grafico nel tempo del traffico HTTP e P2P per la configurazione High Latency raccolto da Grafana/OpenTelemetry.}
    \label{fig:high-latency-grafana}
\end{figure}

Stesso discorso vale per la configurazione High Latency, mostrata in figura \ref{fig:high-latency-grafana}, dove il traffico P2P è nettamente superiore al traffico HTTP, con un rapporto di circa 3:1. In questo caso, i dati raccolti dal player video mostrano un traffico P2P che raggiunge il 77\% del traffico totale in download, leggermente superiore rispetto alla configurazione Normal Latency ma non sorprendente, in quanto i nostri test sono stati eseguiti in un ambiente di rete ideale e con pochi client simultanei rispetto a quelli mostrati nell'articolo originale.

\begin{table}[H]
\centering
\caption{Traffico totale in download per la configurazione High Latency.}
\label{tab:high-latency-traffic}
\begin{tabular}{lrr}
\toprule
\textbf{Metrica} & \textbf{Valore} & \textbf{Percentuale} \\
\midrule
Download totale da peer & 8.28 GiB & 77\% \\
Download totale da server & 2.53 GiB & 23\% \\
Download totale & 10.82 GiB & 100\% \\
\midrule
Rapporto P2P/Server & 3:1 & \\
\bottomrule
\end{tabular}
\end{table}

Il traffico misurato da WebRTC e il campo \textit{data-channel} mostrano un traffico P2P in download totale di 8.84 GiB, con un rapporto di 3:1 rispetto al traffico HTTP totale, anche in questo caso leggermente superiore rispetto alla configurazione Normal Latency.

\begin{figure}[H]
    \centering
    \begin{align}
        \text{P2P/Server Ratio} &= \frac{\text{P2P Traffic}}{\text{HTTP Traffic}} \approx 3 \\
        \text{P2P Percentage} &= \frac{\text{P2P Traffic}}{\text{Total Traffic}} \times 100\% \approx 75\%
    \end{align}
    \caption{Formule matematiche per il calcolo del rapporto P2P/Server e della percentuale di traffico P2P.}
    \label{fig:p2p-ratio-formula}
\end{figure}

Infine, i dati raccolti dai nostri test mostrano che:

\begin{itemize}
    \item Il traffico P2P aumenta progressivamente nel tempo, confermando il comportamento descritto nell'articolo originale
    \item Nei test con High Latency, il traffico P2P ha raggiunto fino al 77\% del traffico totale dopo qualche minuto di riproduzione.
    \item Con Normal Latency, abbiamo osservato un comportamento simile ma con una curva di adozione P2P più graduale, raggiungendo circa il 75\% di traffico P2P in download.
\end{itemize}

\break
\lstset{language=JavaScript}
\begin{lstlisting}[caption={Query MongoDB usata per calcolare il traffico totale in download}, captionpos=b,  basicstyle=\scriptsize]
    [
        {
            $group: {
                _id: "$tags.session",
                maxDownPeers: {
                    $max: "$player.Download Breakdown.Peers"
                },
                maxDownServer: {
                    $max: "$player.Download Breakdown.Server"
                },
            }
        },
        {
            $group: {
                _id: null,
                totalDownPeers: {
                    $sum: "$maxDownPeers"
                },
                totalDownServer: {
                    $sum: "$maxDownServer"
                }
            }
        },
        {
            $project: {
                _id: 0,
                totalDownPeers: 1,
                totalDownServer: 1,
                totalComputedDown: {
                    $sum: [
                        "$totalDownPeers",
                        "$totalDownServer"
                    ]
                }
            }
        },
        {
            $project: {
                totalDownPeers: 1,
                totalDownServer: 1,
                totalComputedDown: 1,
                percentageOfTotalPeers: {
                    $round: {
                        $multiply: [
                            {
                                $divide: [
                                    "$totalDownPeers",
                                    "$totalComputedDown"
                                ]
                            },
                            100
                        ]
                    }
                },
                percentageOfTotalServer: {
                    $round: {
                        $multiply: [
                            {
                                $divide: [
                                    "$totalDownServer",
                                    "$totalComputedDown"
                                ]
                            },
                            100
                        ]
                    }
                },
                ratio: {
                    $round: {
                        $divide: [
                            "$totalDownPeers",
                            "$totalDownServer"
                        ]
                    }
                }
            }
        },
        {
            $sort: {
                ratio: -1
            }
        },
        {
            $limit: 10
        }
    ]
\end{lstlisting}

Tutti i dataset e le query MongoDB usate per l'analisi dei dati sono disponibili pubblicamente qui:
\begin{itemize}
    \item \url{https://gitlab.di.unimi.it/mirko.milovanovic/peertube-collector/-/tree/main/server/peertube%20data}
    \item \url{https://gitlab.di.unimi.it/mirko.milovanovic/Tesi/-/tree/main/peertube/datavis/CRUD}
\end{itemize}

\break
\section{Limitazioni dello studio}

È importante evidenziare alcune limitazioni del nostro approccio:

\begin{itemize}
    \item A differenza dei test di PeerTube che utilizzavano 1000 client simultanei, abbiamo potuto testare con un numero limitato di client a causa di vincoli di risorse.
    \item I nostri client erano distribuiti su data center pubblici con connessioni di qualità superiore rispetto a quelle tipiche degli utenti finali
    \item Non abbiamo potuto testare tutte le combinazioni possibili di configurazioni di rete (diversi tipi di NAT, firewall, ecc.).
    \item La nostra analisi si è concentrata principalmente sulle metriche di rete e non sugli aspetti soggettivi dell'esperienza utente.
\end{itemize}

\section{Prospettive future}

Questo lavoro apre diverse possibilità per ricerche future:

\begin{itemize}
    \item Estendere i test con un numero maggiore di client distribuiti in ambienti di rete più realistici.
    \item Confrontare PeerTube con altre soluzioni P2P per lo streaming video.
    \item Sviluppare metriche standardizzate per valutare l'efficienza dei sistemi di streaming decentralizzato.
    \item Studiare l'impatto di implementazioni WebRTC alternative.
    \item Analizzare i dati aggiuntivi raccolti da WebRTC Internals Exporter per ottenere informazioni più dettagliate sulle prestazioni del sistema P2P come ad esempio: il grafo delle connessioni, la latenza, e altro ancora.
\end{itemize}

\break
\section{Considerazioni finali}

Il nostro lavoro ha confermato che PeerTube rappresenta una soluzione tecnica efficace per la distribuzione decentralizzata di contenuti video. L'implementazione P2P basata su WebRTC offre vantaggi tangibili in termini di riduzione del carico sui server centrali, mantenendo una qualità di streaming adeguata.

La configurazione High Latency si è dimostrata particolarmente efficace nel massimizzare il traffico P2P, rappresentando un ottimo compromesso per contenuti dove la latenza non è critica. Il sistema ha dimostrato una buona resilienza e capacità di adattamento a diverse condizioni di rete.

In un'epoca in cui la centralizzazione dei servizi di streaming solleva preoccupazioni riguardo privacy, censura e sostenibilità economica, PeerTube offre un'alternativa concreta e funzionante. Il nostro studio conferma che, nonostante alcune limitazioni tecniche, l'approccio decentralizzato allo streaming video non solo è tecnicamente possibile ma anche efficiente in termini di utilizzo delle risorse.

Ma soprattutto la metodologia e gli strumenti sviluppati per questo studio potranno essere utilizzati per valutare future implementazioni di tecnologie di streaming decentralizzato basate su WebRTC, contribuendo all'evoluzione di Internet verso un ecosistema più equo e distribuito.

\nocite{*}

\chapter*{Bibliografia}
\addcontentsline{toc}{chapter}{Bibliografia}
\printbibliography[nottype=misc,heading=none]

\chapter*{Sitografia}
\addcontentsline{toc}{chapter}{Sitografia}
\printbibliography[type=misc,heading=none]

\end{document}