Aller au contenu

ft_irc

C++ C++98 Sockets BSD TCP/IP RFC 2810-2813

Implémentation d'un serveur IRC en C++ capable de faire communiquer plusieurs clients en local, avec canaux, opérateurs et un bot bonus.


Présentation

Un serveur IRC qui connecte de multiples clients : salons (#canal), opérateurs, 5 modes de gestion, messagerie privée et diffusion, plus un bot Pierre-Papier-Ciseaux.


Contexte

Projet de la branche réseau du tronc commun 42 : développer un serveur IRC (Internet Relay Chat) en C++98 capable de gérer plusieurs clients simultanément, sur le modèle des serveurs IRC réels (RFC 2810 à 2813).

Pas de client à écrire, le serveur doit être compatible avec les clients IRC existants (HexChat, irssi, WeeChat…). Le sujet interdit fork() et impose un multiplexage unique (poll() ou équivalent comme select()) pour toutes les E/S.


Mon rôle

Projet réalisé en équipe. Contributions portant sur la boucle serveur, le dispatch des commandes, la gestion des canaux et des opérateurs, et le bot bonus - le tout en C++98 sans bibliothèque externe, avec un Makefile aux règles all, clean, fclean, re (sans relink).


Architecture

Un serveur mono-thread : une boucle select() unique surveille tous les descripteurs, accepte les nouveaux clients, lit leurs paquets (avec agrégation des fragments), puis déclenche la commande correspondante.

Architecture de Ft_irc

Schéma de l'architecture de Ft_irc
Étape Rôle Dans le code
Écoute Création du socket TCP, bind, listen constructeur Server (Server.cpp)
Multiplexage Surveillance des sockets prêts à lire boucle select(1024, …) (main.cpp)
Accept Nouveau client → ajout au tableau de clients accept() + addClient()
Lecture Réception + agrégation des paquets partiels recv() + bufTmp(PUSH/DEL)
Dispatch Routage vers la bonne commande ServerSwitch.cpp (switch sur 12 commandes)
Canaux Membres, opérateurs, modes, topic Channel.cpp + ServerMode.cpp

Technologies

Langage
C++98
Norme 42, STL (vector, find), aucune bibliothèque externe.
POO
Avec classes Server, Client, Channel.
Réseau
Sockets BSD TCP/IP
socket, bind, listen, accept, recv, send, close.
TCP seul
Protocole fiable en mode connecté - aucun UDP.
Multiplexage
select()
fd_set + FD_SET, jusqu'à 1024 clients (FD_SETSIZE).
Sans fork()
Boucle mono-thread, toutes les E/S dans un seul select().
Compilation
Makefile
Règles all, clean, fclean, re.
-Wall -Wextra -Werror
Flags d'erreur stricts, compilation C++98.

Fonctionnalités

  • 12 commandes : CAP, PASS, NICK, USER, PRIVMSG, JOIN, KICK, INVITE, TOPIC, MODE, PART, BOT
  • Canaux # : création, propriétaire, opérateurs (préfixe @ dans la liste NAMES), topic
  • 5 modes de canal (MODE) : +i (invitation), +t (topic réservé aux opérateurs), +k (mot de passe), +o (opérateur), +l (limite d'utilisateurs)
  • Messagerie : message privé, diffusion à tout un canal, détection DCC (PRIVMSG … DCC SEND)
  • Bot bonus : Pierre-Papier-Ciseaux (BOT ROCK, BOT PAPER, BOT SCISSORS)
  • Validation des pseudos : unique, max 9 caractères, réservé BOT, broadcast du changement
  • Compatible clients graphiques (HexChat) et nc
  • Réponses numériques IRC (001 welcome, erreurs 461, 464, 471, 473, 475, 482, 501…)

Problème | Solution

Problème Solution
Recevoir des commandes découpées en plusieurs paquets (test ctrl+D du sujet) Tampon bufTmp par client qui agrège les fragments jusqu'au caractère \n avant parsing
Gérer des centaines de clients sans jamais bloquer Une seule boucle select() surveille tous les descripteurs ; pas de fork()
Des pseudos identiques créent des collisions Validation NICK : unicité, longueur max 9, caractères autorisés, nom BOT réservé
Protéger l'accès aux canaux Modes +k (mot de passe), +i (sur invitation), +l (limite) avec réponses d'erreur numériques dédiées

Résultats

  • Serveur ircserv fonctionnel : ./ircserv <port> <password>
  • Testé avec nc et un client graphique (HexChat)
  • Suite de réponses numériques et d'erreurs conforme aux conventions IRC
  • Bonus BOT jouable (Pierre-Papier-Ciseaux)

Lancement

make                 # compilation (all, clean, fclean, re)
./ircserv 6667 toto  # lancement du serveur sur le port 6667
nc 127.0.0.1 6667    # connexion de test, puis : PASS toto / NICK alice / USER alice / JOIN #general

Limite connue

Le serveur n'implémente pas PING/PONG : un client graphique comme HexChat peut afficher « Ping timeout » et se déconnecter après ~60 s d'inactivité.


Ce que j'ai appris

ft_irc m'a appris la discipline d'une boucle d'événements : avec un seul select(), tout le serveur repose sur la règle « ne jamais bloquer », la moindre lecture bloquante gèle tous les autres clients.

J'ai aussi compris que le protocole IRC est une machine à numériques (001, 475, 482…) : chaque cas de refus est un nombre précis, et c'est cette rigueur-là qui rend le serveur compatible avec un vrai client.


Lien

Voir le code