Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
322 changes: 91 additions & 231 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,22 @@
█████ ░░█████ █████████ █████ █████ █████ ░░█████████
░░░░░ ░░░░░ ░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░░░░░
```
Internet Relay Chat project at 42 (a text-based communication protocol on the Internet)<br />

This is the main repository for Internet Relay Chat project at School 42<br />

![Static Badge](https://img.shields.io/badge/-ft__IRC-blue?logo=42&logoColor=white) ![Static Badge](https://img.shields.io/badge/Language-C%2B%2B-blue) ![Static Badge](https://img.shields.io/badge/Protocole-IRC-blue) ![Static Badge](https://img.shields.io/badge/Doc-Doxygen-blue) ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/jmkko/ft_IRC/c-cpp.yml)


---
## IRC protocol

IRC is a text-based communication protocol over TCP/IP. It was first published in 1988 through RFC 1459, updated in 2000 by RFC 2810-2813. An IRC v3 was even proposed later on, which we didn't follow in this project.

Established as a a successor to the Bulletin Board Systems, it grew popular the 1990s, before giving way to proprietary messaging services such as ICQ or MSN.

Yet IRC community remains alive, with IRCNet, Libera Chat or OFTC being today's most popular IRC networks.

## ft_IRC - Subjet
## Subjet

This project is about creating your own IRC server.
You are required to develop an IRC server using the C++ 98 standard.
Expand All @@ -27,140 +35,82 @@ Your executable will be run as follows: `./ircserv <port> <password>`
- Several IRC clients exist. You have to choose one of them as a reference. Your reference client will be used during the evaluation process.
- Communication between client and server has to be done via TCP/IP (v4 or v6).
### Features
- authenticate, set a nickname, a username, join a channel, send and receive private messages using your reference client.
- All the messages sent from one client to a channel have to be forwarded to every other client that joined the channel.
- You must have operators and regular users.
- Commands that are specific to channel operators:
- KICK- Eject a client from the channel
- INVITE- Invite a client to a channel
- TOPIC- Change or view the channel topic
- MODE- Change the channel’s mode:
- i: Set/remove Invite-only channel
- t: Set/remove the restrictions of the TOPIC command to channel operators
- k: Set/remove the channel key (password)
- o: Give/take channel operator privilege
- l: Set/remove the user limit to channel
- message forwarding
- operator status
- Registration and User related commands
- `PASS` Authenticate a client
- `NICK` Change client nickname
- `USER` Register username and real name
- Messaging command
- `PRIVMSG` send a message to a client or a channel
- Channel related commands (some of which might be reserved to channel operators):
- `JOIN` Enter a channel
- `KICK` Eject a client from the channel
- `INVITE` Invite a client to a channel
- `TOPIC` Change or view the channel topic
- `MODE` Change the channel’s mode with following options
- `k`: Set/remove the channel key (password)
- `i`: Set/remove Invite-only channel
- `l`: Set/remove the user limit to channel
- `t`: Set/remove the restrictions of the TOPIC command to channel operators
- `MODE` Also change user mode with
- `o`: Give/take channel operator privilege
### Bonus
- Handle file transfer.
- bot.
- Have a bot
### Extra features
We implemented extra commands not specifically asked in the subject
- PART
- QUIT
- PING
- WHO
- MOTD (message of the day, sent on successful registration)
---

## ft_IRC — Workflow de collaboration

Ce dépôt est le dépôt principal du projet ft_IRC (école 42).
Nous travaillons en équipe de 3 étudiants, chacun sur un fork personnel de ce dépôt.
Toutes les contributions passent par des Pull Requests (PR) vers ce dépôt principal.

### Organisation générale

- `main` — branche stable, propre, toujours fonctionnelle.
- `feature/...` — branches créées dans chaque fork pour développer une fonctionnalité.

### Mise en place du dépôt local (une seule fois)
## Collaboration workflow

1. Forker le dépôt principal
2. Cloner son fork personnel :
```bash
git clone git@github.com:MON-USERNAME/ft_IRC.git
cd ft_IRC
```
3. Relier le dépôt principal en `upstream` :
```bash
git remote add upstream https://github.com/TON-USERNAME/ft_IRC.git
```
4. Vérifier :
```bash
git remote -v
# doit montrer origin -> votre fork, et upstream -> dépôt principal
```
### Workflow de développement
#### Créer une nouvelle fonctionnalité
```bash
# Se mettre à jour avant tout
git checkout main
git pull upstream main
git push origin main
- a main repository with individual forks
- issues to define main features or fixes
- each issue is worked upon on a dedicated branch
- a `main` branch that feature branches must synchronize with and where PR are submitted to
- we strived to follow basic commit message formatting

# Créer une branche de fonctionnalité
git checkout -b feature/ma_fonction
```
cf. [wiki](https://github.com/jmkko/ft_IRC/wiki/Workflow) for details

#### Coder, puis :
```bash
git add .
git commit -m "Ajoute ma_fonction"
git push origin feature/ma_fonction
```
#### Créer une Pull Request (PR)
## Quality and continuous integration workflow

1. Aller sur GitHub → votre fork
2. Sur votre branche → cliquer « Compare & pull request »
3. Vérifier :
- base : `TON-USERNAME/ft_IRC` → `main`
- compare : `MON-USERNAME/ft_IRC` → `feature/ma_fonction`
4. Créer la PR
### Norm and format

### Mettre à jour votre fork
- using `clang-format`
- based upon [LLVM coding rules](https://llvm.org/docs/CodingStandards.html))

Avant de commencer une nouvelle fonctionnalité, synchronisez votre main local et votre fork :
```bash
git checkout main
git pull upstream main
git push origin main
````
### Conventions de code
cf. [wiki](https://github.com/jmkko/ft_IRC/wiki/Norm) for details

- Commits clairs et concis (présent)
✅ Ajoute la gestion du JOIN
❌ J'ai codé join
- Branches : `feature/...` ou `fix/...`
- Jamais coder sur main
- Faire des PR petites et régulières
### Static analysis

### Tests
- using `clang-tidy`

We will strive to make different tests to prevent regressions while shipping new features.
This part of the project is not meant to be evaluated.
Therefore, we will use a more recent standard (c++20) and give a try at new features such as :
- lambdas
- introspection with type traits (ex: printing the name of an exception being thrown)
cf. [wiki](https://github.com/jmkko/ft_IRC/wiki/Static-Analysis) for details

Once implemented, each person implementing a new feature or a fix should be also responsible for the tests.
### Testing

- unit tests to check the output of a function, for normal and edge cases.
- integration test, based on a basic client, to check that a command or series or command produces the expected output from the server.
- a subproject `test` using c++20
- integration tests to prevent regression
- no unit tests (as they might be redundant with integration tests most of the time : projet is not that big)

#### Assertions
cf. [wiki](https://github.com/jmkko/ft_IRC/wiki/Testing) for details

- `AssertUtils` contains utility functions to perform basic checks
### Continuous integration

#### Continuous integration and development
- using Github Actions pipelines : one for build and static checks, one for testing

If possible, we will try to add a Github Action workflow in order to check at each PR that
- the projects compiles
- the norm is respected (using a linter based on [LLVM code rules](https://llvm.org/docs/CodingStandards.html))
- the codebase doesn't have potential bugs (using [CPPcheck](https://github.com/danmar/cppcheck), a static analysis checker)
## Architecture

### Résumé visuel
```bash
+-----------+
| upstream |
| (principal)|
+-----+-----+
^
|
+---------+----------+
| |
+-----+-----+ +-----+-----+
| fork 1 | | fork 2 |
| membre A | | membre B |
+-----------+ +-----------+
```
### Documentation

✨ Important : toujours synchroniser `main` avant de créer une branche de feature.
---
cf [Doxygen generated documentation](https://jmkko.github.io/ft_IRC/html/index.html)

## ft_IRC — Stucture
### UML Class diagram

```mermaid
---
Expand Down Expand Up @@ -389,136 +339,46 @@ classDiagram

---

## ft_IRC - Compétences acquises

Ce projet est un projet synthèse du tronc commun de 42 qui nous a permis de mener
un travail en groupe et d'utiliser toutes les compétences apprises.

- Projet en `C++` - Programmation orientée objet sur un projet complet
- Projet réseau - TCP , Socket , poll
- Protocol `IRC` - Syntaxe des messages
- Les `design pattern` - Nous avons utiliser `Singleton` et `Fabric`
- `Clang tidy` - Respect de règles de nommage et de qualité du code
- `Github` - Nous avons utiliser toutes les services disponibles
- `Fork` - Un repo principale + deux autres repos
- `Actions - Lancement Compilation du projet, puis d'un testeur
- `Rules` - Obligation d'avoir deux validation pour merge sur la main
- `Projet` - Roadmap, Issue (avec branch pour chacune)
- `Wiki`
- `Pages` - pour notre Documentation `Doxygen`
- `Doxygen` - Documentation automatique grace à des commentaires dans notre code
- `Mardown` et `Mermaid` - pour notre README
## Developed skills

This project is a capstone for the 42 common core curriculum, allowing us to collaborate as a team and apply all the skills we’ve acquired throughout the program.

| Skill/Tool | Description |
|--------------------------|-----------------------------------------------------------------------------|
| ![C++](https://img.shields.io/badge/-C++-00599C?logo=c%2B%2B&logoColor=white) | Object-oriented programming on a full-scale project |
| ![Networking](https://img.shields.io/badge/-Networking-0078D4?logo=network&logoColor=white) | TCP, Sockets, `poll` for event-driven I/O |
| ![IRC Protocol](https://img.shields.io/badge/-IRC%20Protocol-4EAA25?logo=irc&logoColor=white) | Message syntax and server-client communication |
| ![Design Patterns](https://img.shields.io/badge/-Design%20Patterns-9370DB?logo=design&logoColor=white) | Implemented `Singleton` and `Factory` patterns |
| ![Clang-Tidy](https://img.shields.io/badge/-Clang--Tidy-21759B?logo=llvm&logoColor=white) | Code quality and naming conventions |
| ![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github&logoColor=white) | Full GitHub workflow: Forks, Actions, Rules, Projects, Wiki, and Pages |
| ![Doxygen](https://img.shields.io/badge/-Doxygen-1E88E5?logo=doxygen&logoColor=white) | Automatic documentation from code comments |
| ![Markdown](https://img.shields.io/badge/-Markdown-000000?logo=markdown&logoColor=white) | Structured documentation with embedded diagrams using `Mermaid` |

---

## ft_IRC - Principales fonctions réseaux

```c++
/*
Crée un socket avec les paramètres passés.
-family définit la famille du socket. Les valeurs principales sont AF_INET pour un socket IPv4, AF_INET6 pour un support IPv6.
-type spécifie le type de socket. Les valeurs principales utilisées sont SOCK_STREAM pour TCP, SOCK_DGRAM pour UDP.
-protocol définit le protocole à utiliser. Il sera dépendant du type de socket et de sa famille. Les valeurs principales sont IPPROTO_TCP pour un socket TCP, IPPROTO_UDP pour un socket UDP.
*/
int socket(int family, int type, int protocol);

//close socket
int close(int socket);
//Les fonctions de cette forme sont les fonctions Host/Home to Network .
//Elles servent à convertir les données numériques de la machine en données
//« réseau ».
short htons(short value);
long htonl(long value);
//Il s’agit des fonctions inverses des hton*.
short ntohs(short value);
long ntohl(long value);
/*
_socket est le socket à connecter.
server la structure représentant le serveur auquel se connecter.
serverlen est la taille de la structure server. socklen_t est un type spécifique aux plateformes UNIX et peut être un int ou unsigned int . Généralement un sizeof(server).

L’appel à cette fonction est bloquant tant que la connexion n’a pas été effectuée. Autrement dit : si cette fonction retourne, c’est que votre connexion a été effectuée et acceptée par l’ordinateur distant. Sauf si elle retourne une erreur bien sûr.

*/
int connect(int _socket, const struct sockaddr* server, socklen_t serverlen);

//ex:
sockaddr_in server;
server.sin_addr.s_addr = inet_addr(const char* ipaddress);
server.sin_family = AF_INET;
server.sin_port = htons(int port);
/*
socket est le socket auquel envoyer les données.
datas les données à envoyer.
len est la taille maximale des données à envoyer en octets.
flags un masque d'options. Généralement 0.
*/
int send(int socket, const void* datas, size_t len, int flags);
int recv(int socket, void* buffer, size_t len, int flags);
/*
La fonction bind est utilisée pour assigner une adresse locale à un socket.

sckt est le socket auquel est assigné l'adresse.
name est la structure à assigner au socket.
namelen est la taille de cette structure -> sizeof.
Retourne SOCKET_ERROR -1 en cas d'erreur, 0 sinon.
*/
int bind(SOCKET sckt, const struct addr* name, int namelen);
//ex
sockaddr_in addr;
addr.sin_addr.s_addr = INADDR_ANY; // indique que toutes les sources seront acceptées
addr.sin_port = htons(port); // toujours penser à traduire le port en réseau<br />
addr.sin_family = AF_INET; // notre socket est TCP
/*
sckt est le socket auquel les clients vont se connecter.
backlog est le nombre de connexions en attente qui peuvent être gérées. La valeur SOMAXCONN peut être utilisée pour laisser le système choisir une valeur correcte selon sa configuration.
*/
int listen(SOCKET sckt, int backlog) ;
/*
Accepte une connexion entrante.

sckt est le socket serveur qui attend les connexions.
addr recevra l'adresse du socket qui se connecte.
addrlen est la taille de la structure pointée par addr.
*/
SOCKET accept(SOCKET sckt, struct sockaddr* addr, int* addrlen);
/*
Permet de récupérer l'adresse IP d'un socket, IPv4 ou IPv6, sous forme lisible.

family est la famille du socket.
src le pointeur vers l'adresse du socket.
dst un pointeur vers un tampon où stocker l'adresse sous forme lisible.
size la taille maximale du tampon.
*/
const char* inet_ntop(int family, const void* src, char* dst, socklen_t size);

/*poll() permet de surveiller plusieurs file descriptors (sockets, fichiers, etc.)
pour détecter quand ils sont prêts pour certaines opérations (lecture, écriture, erreur)
sans bloquer. */
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);

struct pollfd {
int fd; // File descriptor à surveiller
short events; // Événements à surveiller (INPUT)
short revents; // Événements qui se sont produits (OUTPUT)
};
## Main networking functions

- socket creation and closure (`socket`)
- network byte order conversion (`htons`, `ntohs`, `htonl`, `ntohl`)
- connection management (`connect`, `bind`, `listen`, `accept`)
- data transmission (`send`, `recv`)
- event monitoring (`poll`)

```
cf. [wiki](https://github.com/jmkko/ft_IRC/wiki/Networking-functions) for details

---

## ft_IRC - Source - Documentation
## Sources

### RFC
[RFC-145912](https://www.rfc-editor.org/rfc/rfc1459)<br />
[RFC-2812](https://www.rfc-editor.org/rfc/rfc2812)<br />
[Server TCP](https://bousk.developpez.com/cours/reseau-c++/TCP/01-premiers-pas/)<br />
### Networking functions
[Poll](https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/)<br />
[Network programing](https://beej.us/guide/bgnet/html/)<br />
[Server TCP](https://bousk.developpez.com/cours/reseau-c++/TCP/01-premiers-pas/)<br />
### Other interesting resources
[Serveur IRC](https://www.cs.cmu.edu/~srini/15-441/S10/project1/pj1_description.pdf)<br />
[Projet IRC](http://chi.cs.uchicago.edu/chirc/index.html)<br />
[Design Pattern](https://refactoring.guru/fr/design-patterns/singleton)<br />
[Mermaid](https://mermaid.js.org/syntax/classDiagram.html)<br />



2 changes: 2 additions & 0 deletions includes/consts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@
#define FORBIDEN_CHAR_BOT_PROMPT "|;"
#define FORBIDEN_CHAR_CHAN_NAME "\x00\x07\x0D\x0A\x20\x2C\x3A" // NOLINT(clang-diagnostic-null-character)
#define FORBIDEN_CHAR_CHAN_KEY "\x00\x09\x0A\x0B\x0C\x0D\x20" // NOLINT(clang-diagnostic-null-character)
#define FORBIDDEN_CHAR_SERVER_KEY "\x00\x09\x0A\x0B\x0D\x20" // NOLINT(clang-diagnostic-null-character) NUL, HT, LF, VT, CR, space
#define FORBIDEN_CHAR_USER "\x00\x0A\x0D\x20\x40" // NOLINT(clang-diagnostic-null-character)
#define NUMBER_FORB_CCNK 7
#define NUMBER_FORB_CSK 6
#define NUMBER_FORB_CCU 5
#define VALID_CHAN_MODE_NOPARAM "\x69\x74"
#define VALID_CHAN_MODE_PARAM "\x6B\x6C\x6F"
Expand Down
Loading