\documentclass[11pt,a4paper]{article}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{a4}
\usepackage{vmargin}
\usepackage{url}
\usepackage[french]{babel}
\usepackage{latexsym}
\usepackage{verbatim}
\usepackage{alltt}
\usepackage{graphicx}
\usepackage{framed}
\usepackage{xcolor}
\usepackage{listingsutf8}

\input{macros.tex}
\begin{document}
\begin{center}
  {\Large\bf Épreuve de travaux pratiques blanche}\\
    {préparation à l'agrégation d'informatique}\\
    durée 5h00
\end{center}
\vspace*{2cm}
On s’attendra à ce que les candidats traitent de manière au moins partielles les
différentes parties : programmation en OCaml, en C, en Python et SQL.

\section{Programmation}

On s'intéresse dans cette partie à un protocole d'échange de message ressemblant
au protocole IRC (\emph{Internet Relay Chat}) ancêtre des applications modernes
de messageries. Nous décrivons dans un premier temps le protocole. Le serveur
est à implémenter en OCaml, le client en C. Enfin, un « \emph{bot} »
(abréviation robot ou client automatique) est à programmer en SQL et Python.
Vous trouverez en annexe un rappel des différentes fonctions utiles disponibles
dans les bibliothèques standard de ces langages.

L'énoncé fournit aussi des fonctions spécifiques, qui sont expliquées et
commentées dans l'énoncé au moment de leur utilisation.

\subsection{Protocole}
Le protocole est un protocole en mode texte utilisant TCP comme couche de
transport. Les messages échangés entre le client et le serveur ont le format
\begin{center}
  \emph{tag}\texttt{:}\emph{payload}\verb|\n|\\
\end{center}
où \emph{tag} vaut \texttt{CONNECT} ou \texttt{TEXT} et \emph{payload} est une
chaine de caractères quelconque ne contenant ni le caractère nul (de code ASCII
0) ni le caractère \verb|\n| (de code ASCII 10). Tout autre message envoyé entre
le client et le serveur est considéré comme invalide et met fin à la
communication.

Les utilisateurs sont identifiés par un \emph{nick} (abréviation de
\emph{nickname} ou pseudonyme). Un \emph{nick} valide est une suite d'au plus 20
caractères, composée uniquement de chiffres (0 à 9), lettres majuscules ou
minuscules (de a à z ou de A à Z, sans accent) ou des caractères « \texttt{-} »,
«~\texttt{\_}~», «~\texttt{[}~» ou «~\texttt{]}~».

Initialement, le serveur se met en écoute en TCP sur le port 9000.
Lorsqu'un client se connecte au serveur, il lui envoie le message
\begin{center}
  \texttt{CONNECT:}\emph{s}\verb|\n|
\end{center}
où \emph{s} est le \emph{nick} choisi. Si le \emph{s} n'est pas un \emph{nick}
valide ou s'il est déjà utilisé par un autre client, le serveur interrompt la
connexion. Sinon, il renvoie au client le message
\begin{center}
  \texttt{CONNECT:OK}\verb|\n|
\end{center}
à partir de ce moment, la connexion est établie. Un client dont le \emph{nick} est \emph{s} peut envoyer
au serveur un message
\begin{center}
  \texttt{TEXT:}\emph{p}\verb|\n|
\end{center}
sur réception d'un tel message, le serveur va alors diffuser, à tous les autres
clients que $s$, le message $p$ en le préfixant de $s$, et d'un caractère \texttt{>}
suivi d'un espace:
\begin{center}
  \texttt{TEXT:}\emph{s}\texttt{> }\emph{p}\verb|\n|
\end{center}

\subsection{Serveur (programmation réseau et parallèle en OCaml)}
Le serveur est à programmer en OCaml, en n'utilisant que des fonctions de la
bibliothèque standard, de la bibliothèque \texttt{Unix} et de la bibliothèque
\emph{thread}. On fournit un code initial
(fichier \texttt{server/server.ml}), reproduit à la figure~\ref{fig:serv}.
\begin{figure}[th!]
  \ocamlexternal{files/server/server.ml}
  \caption{Le fichier \texttt{server.ml}}
  \label{fig:serv}
\end{figure}
\begin{description}
  \item[question 1] On demande de compléter le fichier \texttt{server.ml} afin
    d'ajouter le code de traitement d'un client une fois la connexion établie. On donne les indications suivantes :
    \begin{itemize}
      \item le code de gestion de chaque client (L.8) est démarré dans un \emph{thread} (processus léger) séparé (L.24)
      \item la fonction de traitement du client prend en argument la socket
            permettant de parler au serveur, deux canaux et l'adresse du client ainsi que son port sous forme d'une chaine de caractères.
            Les canaux utilisent la socket comme descripteur de fichier
            sous-jacent. Ils permettent donc de lire et d'écrire de façon
            structurée plus agréablement qu'en utilisant directement la socket.
      \item une écriture sur \ocamlinline{outc} doit être suivie de
            \ocamlinline{flush(outc)} afin de garantir que les octets écrits ne restent
            pas dans un buffer intermédiaire.
      \item Pour déconnecter le client, on fermera les canaux au moyen de
            \ocamlinline{close_in} et \ocamlinline{close_out} et la socket au moyen de
            \ocamlinline{close} (fonction du module \ocamlinline{Unix}).
      \item le fichier doit être compilé avec
            \begin{verbatim}
ocamlopt -o server -I +threads unix.cmxa threads.cmxa server.ml
\end{verbatim}
      \item il est évidemment possible de rajouter toute autre définition nécessaire au fichier,
            sans cependant modifier le code des lignes 11 à 27.
      \item il est aussi possible d'ajouter du code dans des fichiers séparés. On les compilera alors avec :\\[5mm]
\hspace*{-1.8cm}\begin{minipage}{\textwidth}
\begin{verbatim}
ocamlopt -c -I +threads f1.mli
ocamlopt -c -I +threads f1.ml
ocamlopt -c -I +threads f2.mli
ocamlopt -c -I +threads f2.ml
ocamlopt -o server -I +threads unix.cmxa threads.cmxa f1.cmx f2.cmx server.ml
    \end{verbatim}
  \end{minipage}

\noindent en ordonnant les fichiers \texttt{.cmx} sur la ligne de commande finale par
ordre de dépendance.
    \end{itemize}
\end{description}
\begin{reponse}
  On s'attend ici que le candidat propose soit un client basique en OCaml soit
  un script utilisant par exemple \texttt{netcat}.
\end{reponse}
\subsection{Client (programmation réseau et parallèle en C)}
On demande d'implémenter en C un client en mode texte, fonctionnant dans un
terminal. Dans toute cette section, on appelle «~chaine de caractères~» une suite
d'octets (type \texttt{char}) terminée par un octet nul.
\subsubsection{Gestion du réseau en C}
\begin{description}
  \item[question 2] Programmer le début d'un client en mode texte. Ce dernier
  doit prendre exactement trois arguments sur la ligne de commande
    \begin{itemize}
      \item l'adresse ou le nom du serveur
      \item le numéro de port
      \item le \emph{nick} choisi
    \end{itemize}
    Si la ligne de commande n'est pas au bon format, que le \emph{nick} ne
    respecte pas les contraintes demandées le programme échoue avec un code de
    sortie 1. Le client essaye ensuite d'établir une connexion TCP avec le
    serveur, de lui envoyer le message de connexion et de recevoir le message
    d'acquittement. Si à un quelconque moment un problème se produit, le client
    quitte avec le code de sortie 2. On pourra utiliser l'adresse locale
    127.0.0.1 pour contacter un serveur s'exécutant sur la même machine que le
    client.
\end{description}
Comme dans la partie en OCaml, il est suggéré
d'encapsuler le descripteur de fichier de la \emph{socket} dans un objet
\cinline{FILE*} de la bibliothèque standard C afin de disposer de fonction de
haut niveau pour lire et écrire des chaines de caractères. Attention, les
écritures sur de tels \cinline{FILE*} sont généralement accumulées dans un
tampon interne. On peut forcer leur écriture sur le descripteur sous-jacent
avec la fonction \cinline{fflush}. Une façon d'encapsuler un descripteur est :
\begin{C}
  //un descripteur de fichier fdescr, par exemple une socket
  FILE * infile = fdopen(dup(fdescr), "rb");
  FILE * outfile = fdopen(dup(fdescr), "wb");
  //lire sur infile et écrire sur outfile
\end{C}

\subsubsection{Gestion de la concurrence en C}
Afin d'avoir une interface conviviale, on propose la petite
bibliothèque dont l'entête est donnée à la figure~\ref{fig:screen}.
\begin{figure}
  \cexternal{files/client/screen.h}
  \caption{L'interface de la bibliothèque \texttt{screen}}
  \label{fig:screen}
\end{figure}
Avec cette bibliothèque il est possible de concevoir une interface comme celle de la figure~\ref{fig:ex}.
\begin{figure}[th!]
  \begin{framed}
    \begin{alltt}
Alice[oklm]> Hello, ça va ?
charlie> oui merci !
Bob> Oui tranquille et toi ?
Bob> Passé un bon week-end ?
Alice[oklm]> Oui très bon, merci !
=========================================================================
charlie> beaucoup de révisi\rule{0.5em}{0.75em}
    \end{alltt}
  \end{framed}
  \caption{L'interface texte}
  \label{fig:ex}
\end{figure}
\noindent Cette figure représente un écran initialisé avec un appel à
\cinline{screen_init("charlie> ")}. En effet, la zone se situant sous les
«~\texttt{===\ldots}~» est la zone de saisie. L'utilisateur peut à tout moment y
écrire des caractères autre qu'un retour charriot (le rectangle noir représente
la position du curseur). La fonction \cinline{screen_read_input} bloque jusqu'à
ce que l'utilisateur valide sa saisie avec la touche entrée. La chaine saisie
est alors envoyée. Pour les affichages, la fonction \cinline{screen_print_line}
prend en argument l'écran, le numéro de la ligne sur laquelle afficher et la
chaine à afficher. La fonction \cinline{screen_get_size} permet de connaitre le
nombre de lignes et de colonnes de l'écran.

\begin{description}
  \item[question 3] programmer un type de liste chainées pour lesquelles les
    valeurs stockées sont des chaines de caractères. Une telle liste représente
    l'historique des messages reçus, la tête de liste étant le message le plus
    récent.
  \item[question 4] programmer une fonction d'affichage de cette liste chainée,
    depuis la ligne se trouvant juste au dessus du séparateur jusqu'au haut de
    l'écran.
  \item[question 5] programmer l'interface graphique, en utilisant la
    bibliothèque fournie ainsi que des \emph{threads}. Sur saisie d'un message par
    l'utilisateur, ce dernier doit être ajouté dans son historique et envoyé au
    serveur. Sur réception d'un message \begin{center}
      \verb|TEXT:foo> ...\n|
    \end{center}
    la partie
    suivant les «~\texttt{:}~» jusqu'au «~\verb|\n|~» exclu doit être ajouté à
    l'historique et ce dernier entièrement ré-affiché. Enfin, si le texte de
    l'utilisateur commence par «~\verb|/QUIT|~» le programme se termine.
\end{description}

\subsection{Programmation en SQL et Python}
On considère le code Python du \emph{bot} partiellement donné en
figure~\ref{fig:bot}.
\begin{figure}[th!]
  \pythonexternal{files/bot/bot.py}
  \caption{Le code du \emph{bot} (fichier \texttt{bot/bot.py})}
  \label{fig:bot}
\end{figure}
La fonction \pythoninline{bot} prend en argument :
\begin{description}
  \item[\texttt{serv}] une paire de chaines de caractères représentant l'adresse
  IP du serveur et son nom d'hôte. Si ce dernier n'est pas connu, alors la
  chaine correspondante est vide.
  \item[\texttt{socket}] une \emph{socket} représentant la connexion au serveur de discussion
  \item[\texttt{dbcn}] un objet \texttt{Connection} représentant la connexion à une base de donnée. 
\end{description}
La fonction se met en attente de message (de la part du serveur de discussion).
Sur réception d'un message valide, il le décompose pour obtenir d'une part le
\emph{nick} et d'autre part le message. Il appelle alors la fonction
\pythoninline{log_message}, non détaillée, qui les enregistre alors dans une
base de données avec l'identifiant du serveur et l'heure courante, au format
\emph{Unix} (nombre de secondes écoulées depuis le 1\up{er} janvier 1970
00:00:00 GMT). De plus, si le message commence par \texttt{ !STATS} le
\emph{bot} appelle la fonction \pythoninline{print_stats}, non-détaillée, qui calcule des statistiques et 
les écrits sur le serveur de discussion (en simulant un participant qui parle).

Plusieurs instances de ce programme peuvent être exécutées et connectés à des
serveurs de discussion différents. On fait l'hypothèse (simpliste) qu'un
\emph{nick} représente le même utilisateur sur tous les serveurs de discussion.
On suppose aussi que tous les \emph{bots} sont connectés à un unique serveur de
bases de données.
\begin{description}
  \item[question 6] proposer une modélisation de la base de données comportant au moins deux tables. Vous
    décrirez précisément les tables, les types et les contraintes en donnant
    les ordres de création de tables. Vous justifierez le choix des types.

  \item[question 7] proposer des requêtes SQL qui utilisent votre modélisation
    et permettent de calculer  les statistiques suivantes
    \begin{enumerate}
      \item Le nombre de messages stockés
      \item Le nombre d'utilisateurs distincts
      \item Le nombre de serveurs distincts dont le nom d'hôte se termine par
      \texttt{.fr}
      \item Le nombre d'utilisateurs distincts sur un serveur \texttt{'rezosup.fr'} 
      \item Le nombre de messages contenant la sous-chaine \texttt{informatique} (en minuscules)
      \item L'ensemble sans doublon des utilisateurs du serveur $s$ ayant envoyé
            des messages avant le 1\up{er} janvier 2020
      \item Pour chaque utilisateur, le nombre de messages envoyés si ce dernier
            est plus grand que 30, triés par ordre décroissant de nombre de messages
      \item Les utilisateurs n'ayant jamais envoyé de message sur le serveur \texttt{'rezosup.fr'} 
      \item Les utilisateurs ayant envoyé globalement plus de 100 messages et
      qui ont discuté sur le serveur \texttt{'rezosup.fr'}
    \end{enumerate}

\item[question 8] Un problème peut se produire si deux
\emph{bots} sont connectés au même serveur de discussion car les messages de ce
dernier vont être comptés deux fois. Proposer une solution à ce problème utilisant
la base de données (en fournissant du code SQL d'exemple).

\item[question 9] On détaille maintenant l'API d'une connexion à la base de données par un exemple : 
\begin{python}
#dbcn est un object Connection
cur = dbcn.cursor()   #objet pour exécuter un ordre SQL
tab = cur.execute("SELECT * FROM T")
\end{python} 
Après exécution de ce code, \pythoninline{tab} est un itérable (utilisable dans
une boucle \pythoninline{for .. in}) de dictionnaires dont les clés sont les
noms des colonnes sélectionnées et les valeurs celles de la ligne en cours.
Écrire une fonction Python \pythoninline{print_stats_html} qui écrit sur la
sortie standard le résultat d'une requête calculant le nombre de messages par
serveur sous la forme d'un fichier HTML. Ce dernier devra utiliser une
\texttt{<table>} dont les en-têtes sont les noms des colonnes du résultat de la
requête et dont les lignes paires ont un fond blanc et les lignes impaires un
fond gris.
\end{description}
\pagebreak
\appendix
\noindent{\Huge\bf\appendixname}
\section{Référence OCaml}
\paragraph{Entrées/sorties sur les cannaux, parallélisme}
\begin{description}
  \item[\texttt{in\_channel} :] type d'un canal de lecture
  \item[\texttt{out\_channel} :] type d'un canal d'écriture
  \item[\texttt{output\_char} :] écriture d'un caractère sur un canal
  \item[\texttt{output\_string} :] écriture d'un caractère sur un canal
  \item[\texttt{input\_line} :] lecture d'une ligne (terminée par \ocamlinline{'\\n'}) sur un canal 
  \item[\texttt{close\_in}:] fermeture d'un canal de lecture
  \item[\texttt{close\_out} :] fermeture d'un canal d'écriture
  \item[\texttt{flush} :] vidage du tampon interne d'un canal d'écriture
  \item[\texttt{Mutex.create} :] création d'un mutex (bibliothèque \texttt{threads})
  \item[\texttt{Mutex.lock} :] verrouillage d'un mutex (bibliothèque \texttt{threads})
  \item[\texttt{Mutex.unlock} :] déverrouillage d'un mutex (bibliothèque \texttt{threads})         
\end{description}
\section{Référence C}
Hors fonctionnalités de la bibliothèque standard C, les fonctions ci-dessous
peuvent être utiles.
\paragraph{Chaine de caractères, formatage}
\begin{description}
  \item[\texttt{strncmp} :] comparaison des $n$ premiers caractères de deux chaines données
  \item[\texttt{fprintf} :] écriture formatée dans un \cinline{FILE*}
  \item[\texttt{snprintf}:] écriture formatée dans un tableau de caractères de taille au plus $n$
  \item[\texttt{fflush} :] vidage du tampon interne d'un \cinline{FILE*} et
    écriture sur le descripteur de fichier sous-jacent
  \item[\texttt{isalnum} :] teste si un caractère est alphanumérique
  \item[\texttt{getline} :] lecture d'une ligne (terminée par \cinline{'\\n'})
    d'un \cinline{FILE*} avec allocation automatique
  \item[\texttt{fdopen} :] création d'un \cinline{FILE*} à partir d'un descripteur de fichier
  \item[\texttt{fclose} :] fermeture d'un \cinline{FILE*} 
\end{description}
\paragraph{Système,réseau,parallélisme}
\begin{description}
  \item[\texttt{read} :] lecture sur un descripteur de fichier
  \item[\texttt{write} :] écriture sur un descripteur de fichier
  \item[\texttt{close}:] fermeture d'un descripteur de fichier 
  \item[\texttt{memset} :] initialisation d'une zone mémoire
  \item[\texttt{getaddrinfo}:] traduction d'adresses et de services réseaux
  \item[\texttt{socket} :] création d'une \emph{socket}
  \item[\texttt{bind} :] association d'une adresse à une \emph{socket}
  \item[\texttt{listen} :] mise en mode passif d'une \emph{socket}
  \item[\texttt{accept} :] attendre des connexions sur une \emph{socket}
  \item[\texttt{connect} :] débuter une connexion sur une \emph{socket}
  \item[\texttt{send} :] envoi de données sur une \emph{socket}
  \item[\texttt{recv} :] réception de données sur une \emph{socket}
  \item[\texttt{pthread\_create} :] création d'un nouveau \emph{thread}
  \item[\texttt{pthread\_cancel} :] arrêt d'un \emph{thread}
  \item[\texttt{pthread\_join} :] attente de l'arrêt d'un \emph{thread}
  \item[\texttt{pthread\_mutex\_t} :] type d'un mutex
  \item[\texttt{pthread\_mutex\_init} :] initialisation d'un mutex (pile ou tas)
  \item[\texttt{PTHREAD\_MUTEX\_INITIALIZER} :] initialisation d'un mutex (global)
  \item[\texttt{pthread\_mutex\_lock} :] verrouillage d'un mutex
  \item[\texttt{pthread\_mutex\_unlock} :] déverrouillage d'un mutex
  \item[\texttt{pthread\_mutex\_destroy} :] destruction d'un mutex
\end{description}


\end{document}
