Welcome to the ft_irc project repository!
ft_irc is an IRC (Internet Relay Chat) server implemented in C++98. It represents a significant milestone as the first project undertaken in C++ following the completion of the CPP Piscine at School 42. IRC is a widely-used text-based communication protocol facilitating real-time messaging in both group channels and direct messages.
The primary goal of this project is to develop a fully-functional IRC server that meets specific requirements and features outlined in the project specifications. Limechat was utilized as the client for testing and interaction with the IRC server.
In computer networking, a socket is one endpoint of a two-way communication link between two programs running on the network. Sockets are used to establish communication between a client and a server over a network, such as the Internet. They provide a means of communication that allows processes to exchange data.
The server setup involves creating a socket, binding it to a specific IP address and port, and listening for incoming connections. Here's a brief overview of the server setup process in the project:
-
Creating the Socket: The
socket()
system call is used to create a new socket. In the project, this socket is configured for streaming communication (SOCK_STREAM
) and uses the TCP protocol. -
Binding the Socket: The
bind()
system call is used to associate the socket with a specific IP address and port number. This allows the server to receive incoming connections on that IP address and port. -
Setting Socket Options: Optional socket options can be set using the
setsockopt()
system call. In the project, theSO_REUSEADDR
option is set to allow the reuse of local addresses and ports. -
Listening for Connections: The
listen()
system call puts the socket in a listening state, allowing it to accept incoming connections from clients. The maximum number of pending connections that can be queued is specified as an argument tolisten()
. -
Accepting Connections: When a client tries to connect to the server, the
accept()
system call is used to accept the connection. This creates a new socket for the client and returns a file descriptor that represents the connection.
poll()
is a system call used in Unix and Unix-like operating systems to monitor multiple file descriptors to see if I/O is possible on any of them.
It is an efficient way to handle I/O operations on multiple sockets or file descriptors simultaneously without the need for busy waiting or managing multiple threads.
In the context of this project, poll()
is utilized to efficiently manage I/O operations on multiple client connections to the IRC server.
Instead of handling each connection sequentially or using blocking I/O operations, poll()
allows the server to handle multiple connections concurrently, making the server more responsive and efficient.
In the project, the poll()
function is used to manage multiple client connections efficiently. Here's how poll()
is used in the server code:
-
Initializing
pollfd
Structures: Before entering the main event loop,pollfd
structures are initialized for the server socket and each client socket. These structures specify the file descriptors to monitor for events and the types of events to monitor. -
Waiting for Events: The server enters a loop where it waits for events using the
poll()
function. The server can wait for events on multiple file descriptors simultaneously, allowing it to handle multiple client connections concurrently. -
Handling Events: When an event occurs on a file descriptor (e.g., data available for reading), the server reacts accordingly. For example, if data is available for reading on a client socket, the server reads the data and processes it.
-
Non-blocking I/O: The sockets used in the project are set to non-blocking mode using the
fcntl()
system call. This ensures that I/O operations on the sockets do not block, allowing the server to handle multiple connections efficiently without waiting for each operation to complete.
- Clone this repository
- Compile the project:
make all
- Run the program using the below command:
./ircserv <port> <password>
Once the server is compiled and running, follow these steps to connect to it:
- Open Limechat
- In the bottom right window, right-click and select "Add Server"
- Fill in the following details:
- Network name: Enter any name.
- Server: Enter "localhost".
- Port: Enter the port used when running the server.
- Server Password: Provide the password used when running the server.
- Nickname: Choose any nickname.
- The server should appear in the right bottom window. Right-click on it and select "Connect".
Alternatively, you can use the Netcat (nc) command in the terminal to connect to the server:
nc localhost <port>
Replace <port>
with the actual port number used when running the server.
Once a user is connected to the server, they need to get authenticated which is known as 'server handshake'. For that, the user needs to pass the below three commands with the appropriate parameters:
- Description: Authenticate with the server.
- Syntax:
PASS <password>
- Example: PASS mypassword
- Description: Set or change the user's nickname. Required initially to authenticate with the server but can also be used at a later stage to change the nickname
- Syntax:
NICK <nickname>
- Example: NICK user123
- Description: Set username and realname while connecting to the server.
- Syntax:
USER <username> <hostname> <servername> <realname>
- Example: USER user123 * * :Real Name
- Description: Join an existing channel. If the channel does not exist, it will be created. This can be used to join several channels at the same time.
- Syntax:
JOIN #<channel>
- Example: JOIN #general
- Description: Change or view the topic of a channel.
- Syntax:
TOPIC #<channel> : [<topic>]
- Example: TOPIC #general : New topic here
If <topic>
is not provided, this command will show the topic of the channel.
- Description: Invite a user to a channel.
- Syntax:
INVITE <nick> #<channel>
- Example: INVITE user123 #general
- Description: Remove a user from a channel.
- Syntax:
KICK #<channel> <nick> : [<reason>]
- Example: KICK #general user123 : Spamming
- Description: Leave a channel. It can be used to leave several channels at the same time.
- Syntax:
PART #<channel> : [<comment>]
- Example: PART #general : Leaving the conversation
-
Description: Send a private message to a user or a message to a channel.
-
Syntax:
PRIVMSG <nick of receiver> / #<channel> :<message>
-
Examples:
**PRIVMSG user123 :Hello there!** **PRIVMSG #general :Hello there!**
- 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.
- Description: Disconnect from the server.
- Syntax: `QUIT