mirror of
https://github.com/Ladebeze66/ft_irc.git
synced 2025-12-16 05:58:09 +01:00
first
This commit is contained in:
parent
a1a7eb5b57
commit
be09476005
52
ft_irc/.vscode/settings.json
vendored
Normal file
52
ft_irc/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"bit": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"compare": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"cstdarg": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"cwctype": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"vector": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"string_view": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"initializer_list": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"iostream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numbers": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -6,7 +6,7 @@
|
|||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:07:00 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:07:00 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:33:20 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/10 14:10:35 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -17,6 +17,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
@ -25,12 +26,16 @@ public:
|
|||||||
|
|
||||||
void sendMessage(const std::string& message);
|
void sendMessage(const std::string& message);
|
||||||
std::string receiveMessage();
|
std::string receiveMessage();
|
||||||
void setNickname(const std::string& newNickname); // Ajout de la méthode setNickname
|
void setNickname(const std::string& newNickname);
|
||||||
|
std::string getNickname() const; // Ajout de la méthode getNickname
|
||||||
|
int getSocket() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int socket;
|
int socket;
|
||||||
std::string nickname;
|
std::string nickname; // Assurez-vous que cette donnée membre est accessible via getNickname
|
||||||
std::string username;
|
std::string username;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:01:12 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:01:12 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:39:02 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/10 14:10:44 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -15,8 +15,6 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Client.hpp"
|
|
||||||
#include "CommandHandler.hpp"
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -24,7 +22,21 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "Client.hpp" // Assurez-vous que Client est inclus avant Server
|
||||||
|
#include "CommandHandler.hpp"
|
||||||
|
|
||||||
|
class Server; // Déclaration anticipée de Server si nécessaire
|
||||||
|
|
||||||
|
// Structure pour passer des données aux threads
|
||||||
|
struct ClientContext {
|
||||||
|
Client* client;
|
||||||
|
Server* server;
|
||||||
|
CommandHandler* cmdHandler;
|
||||||
|
|
||||||
|
ClientContext(Client* c, Server* s, CommandHandler* ch) : client(c), server(s), cmdHandler(ch) {}
|
||||||
|
};
|
||||||
class Server {
|
class Server {
|
||||||
public:
|
public:
|
||||||
Server(int port, const std::string& password);
|
Server(int port, const std::string& password);
|
||||||
@ -37,9 +49,11 @@ private:
|
|||||||
int port; // Port number to bind the server
|
int port; // Port number to bind the server
|
||||||
std::string password; // Server password for client connections
|
std::string password; // Server password for client connections
|
||||||
bool running; // Server running status
|
bool running; // Server running status
|
||||||
std::vector<Client*> clients; // List of connected clients
|
std::vector<pthread_t> threads; // List of threads for client management
|
||||||
|
|
||||||
void manageClient(Client* client, CommandHandler& cmdHandler);
|
static void *manageClient(void *clientContext); // Static to be compatible with pthread
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SERVER_HPP
|
#endif // SERVER_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
ft_irc/ircserv
BIN
ft_irc/ircserv
Binary file not shown.
@ -6,11 +6,13 @@
|
|||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:33:11 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/10 13:33:20 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#include "Client.hpp"
|
#include "Client.hpp"
|
||||||
|
#include <cstring>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
Client::Client(int socket, const std::string& nickname, const std::string& username)
|
Client::Client(int socket, const std::string& nickname, const std::string& username)
|
||||||
: socket(socket), nickname(nickname), username(username) {}
|
: socket(socket), nickname(nickname), username(username) {}
|
||||||
@ -20,19 +22,38 @@ Client::~Client() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Client::sendMessage(const std::string& message) {
|
void Client::sendMessage(const std::string& message) {
|
||||||
|
std::cout << "Sending message: " << message << std::endl;
|
||||||
send(socket, message.c_str(), message.size(), 0);
|
send(socket, message.c_str(), message.size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Client::receiveMessage() {
|
std::string Client::receiveMessage() {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
std::memset(buffer, 0, sizeof(buffer));
|
std::memset(buffer, 0, sizeof(buffer));
|
||||||
int len = recv(socket, buffer, sizeof(buffer), 0);
|
int len = recv(socket, buffer, sizeof(buffer) - 1, 0);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
return std::string(buffer, len);
|
buffer[len] = '\0'; // Ensure null termination
|
||||||
|
std::string received(buffer);
|
||||||
|
// Erase newline and carriage return characters
|
||||||
|
size_t pos;
|
||||||
|
while ((pos = received.find_first_of("\r\n")) != std::string::npos) {
|
||||||
|
received.erase(pos, 1);
|
||||||
|
}
|
||||||
|
std::cout << "Received message: [" << received << "]" << std::endl;
|
||||||
|
return received;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::setNickname(const std::string& newNickname) {
|
void Client::setNickname(const std::string& newNickname) {
|
||||||
nickname = newNickname;
|
nickname = newNickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Client::getNickname() const {
|
||||||
|
return nickname;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Client::getSocket() const {
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:19:15 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:19:15 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:33:32 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/10 12:33:00 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -62,9 +62,11 @@ void CommandHandler::handleNick(const std::string& command, Client* client) {
|
|||||||
std::vector<std::string> tokens = split(command, ' ');
|
std::vector<std::string> tokens = split(command, ' ');
|
||||||
if (tokens.size() > 1) {
|
if (tokens.size() > 1) {
|
||||||
client->setNickname(tokens[1]);
|
client->setNickname(tokens[1]);
|
||||||
|
std::cout << "Nickname set to: " << tokens[1] << std::endl; // Afficher et enregistrer l'action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CommandHandler::handlePrivmsg(const std::string& command, Client* client) {
|
void CommandHandler::handlePrivmsg(const std::string& command, Client* client) {
|
||||||
std::vector<std::string> tokens = split(command, ' ');
|
std::vector<std::string> tokens = split(command, ' ');
|
||||||
if (tokens.size() > 2) {
|
if (tokens.size() > 2) {
|
||||||
|
|||||||
@ -6,90 +6,115 @@
|
|||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:01:34 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:01:34 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:48:31 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/10 14:13:02 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
// Server.cpp
|
||||||
#include "Server.hpp"
|
#include "Server.hpp"
|
||||||
|
|
||||||
Server::Server(int port, const std::string& password) : port(port), password(password), running(false) {}
|
Server::Server(int port, const std::string& password) : port(port), password(password), running(false) {}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server() {
|
||||||
// Nettoyage des ressources si nécessaire
|
for (size_t i = 0; i < threads.size(); ++i) {
|
||||||
close(listener); // Assurez-vous de fermer le socket d'écoute
|
if (threads[i]) pthread_join(threads[i], NULL);
|
||||||
// Nettoyage des clients dynamiquement alloués, si vous ne l'avez pas déjà fait
|
|
||||||
for (std::vector<Client*>::iterator it = clients.begin(); it != clients.end(); ++it) {
|
|
||||||
delete *it;
|
|
||||||
}
|
}
|
||||||
|
close(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::initialize() {
|
bool Server::initialize() {
|
||||||
struct sockaddr_in server_addr;
|
struct sockaddr_in server_addr;
|
||||||
|
|
||||||
// Création du socket
|
|
||||||
listener = socket(AF_INET, SOCK_STREAM, 0);
|
listener = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (listener == -1) {
|
if (listener == -1) {
|
||||||
std::cerr << "Error creating socket: " << strerror(errno) << std::endl;
|
std::cerr << "Error creating socket: " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Préparation de l'adresse du serveur
|
|
||||||
memset(&server_addr, 0, sizeof(server_addr));
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
server_addr.sin_family = AF_INET;
|
server_addr.sin_family = AF_INET;
|
||||||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
server_addr.sin_port = htons(port);
|
server_addr.sin_port = htons(port);
|
||||||
|
|
||||||
// Liaison du socket
|
|
||||||
if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
|
if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
|
||||||
std::cerr << "Error binding socket: " << strerror(errno) << std::endl;
|
std::cerr << "Error binding socket: " << strerror(errno) << std::endl;
|
||||||
close(listener);
|
close(listener);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mise en écoute du socket
|
if (listen(listener, 10) == -1) {
|
||||||
if (listen(listener, 10) == -1) { // backlog set to 10
|
|
||||||
std::cerr << "Error listening: " << strerror(errno) << std::endl;
|
std::cerr << "Error listening: " << strerror(errno) << std::endl;
|
||||||
close(listener);
|
close(listener);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Server initialized and listening on port " << port << std::endl;
|
std::cout << "Server initialized and listening on port " << port << std::endl;
|
||||||
|
running = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::run() {
|
void Server::run() {
|
||||||
running = true;
|
if (!running) {
|
||||||
|
std::cerr << "Server not initialized or already running." << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandHandler cmdHandler;
|
||||||
|
while (running) {
|
||||||
struct sockaddr_in client_addr;
|
struct sockaddr_in client_addr;
|
||||||
socklen_t client_len = sizeof(client_addr);
|
socklen_t client_len = sizeof(client_addr);
|
||||||
CommandHandler cmdHandler;
|
|
||||||
|
|
||||||
while (running) {
|
|
||||||
int client_sock = accept(listener, (struct sockaddr *)&client_addr, &client_len);
|
int client_sock = accept(listener, (struct sockaddr *)&client_addr, &client_len);
|
||||||
if (client_sock == -1) {
|
if (client_sock == -1) {
|
||||||
std::cerr << "Error accepting connection: " << strerror(errno) << std::endl;
|
std::cerr << "Error accepting connection: " << strerror(errno) << std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Client connected: " << client_sock << std::endl;
|
|
||||||
try {
|
|
||||||
// Créez un nouvel objet Client avec des valeurs par défaut pour nickname et username
|
|
||||||
Client* newClient = new Client(client_sock, "DefaultNickname", "DefaultUsername");
|
Client* newClient = new Client(client_sock, "DefaultNickname", "DefaultUsername");
|
||||||
std::string welcomeMsg = "Welcome to the IRC Server!\n";
|
ClientContext* context = new ClientContext(newClient, this, &cmdHandler);
|
||||||
newClient->sendMessage(welcomeMsg);
|
pthread_t thread;
|
||||||
manageClient(newClient, cmdHandler);
|
pthread_create(&thread, NULL, &Server::manageClient, context);
|
||||||
} catch (const std::exception& e) {
|
pthread_detach(thread);
|
||||||
std::cerr << "Exception handling client: " << e.what() << std::endl;
|
threads.push_back(thread);
|
||||||
close(client_sock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::manageClient(Client* client, CommandHandler& cmdHandler) {
|
void* Server::manageClient(void *clientContext) {
|
||||||
// Boucle pour recevoir les commandes du client
|
ClientContext* ctx = static_cast<ClientContext*>(clientContext);
|
||||||
while (running) {
|
Client* client = ctx->client;
|
||||||
std::string command = client->receiveMessage();
|
Server* server = ctx->server;
|
||||||
if (command.empty()) break; // Client disconnected
|
|
||||||
cmdHandler.handleCommand(command, client);
|
client->sendMessage("Welcome to the IRC Server!\n");
|
||||||
|
client->sendMessage("Password required:\n");
|
||||||
|
|
||||||
|
std::string passwordInput = client->receiveMessage();
|
||||||
|
std::cout << "Received password: [" << passwordInput << "]" << std::endl;
|
||||||
|
|
||||||
|
if (passwordInput != server->password) {
|
||||||
|
client->sendMessage("Incorrect password.\n");
|
||||||
|
std::cout << "Password mismatch." << std::endl;
|
||||||
|
close(client->getSocket());
|
||||||
|
delete client;
|
||||||
|
delete ctx;
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
delete client; // Cleanup when client disconnects
|
|
||||||
|
client->sendMessage("Password correct.\n");
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
while ((command = client->receiveMessage()) != "") {
|
||||||
|
ctx->cmdHandler->handleCommand(command, client);
|
||||||
|
if (command == "QUIT") break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(client->getSocket());
|
||||||
|
delete client;
|
||||||
|
delete ctx;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -317,3 +317,5 @@ Scalabilité : Pensez à la scalabilité de votre serveur avec ces nouvelles fon
|
|||||||
Conformité aux standards : Même pour les fonctionnalités bonus, tenez-vous aux standards IRC et aux bonnes pratiques de programmation pour garantir que votre serveur peut interagir correctement avec d'autres clients et serveurs IRC.
|
Conformité aux standards : Même pour les fonctionnalités bonus, tenez-vous aux standards IRC et aux bonnes pratiques de programmation pour garantir que votre serveur peut interagir correctement avec d'autres clients et serveurs IRC.
|
||||||
|
|
||||||
Ces fonctionnalités bonus peuvent grandement enrichir l'expérience utilisateur sur votre serveur IRC, le rendant plus attractif et plus utile pour vos utilisateurs.
|
Ces fonctionnalités bonus peuvent grandement enrichir l'expérience utilisateur sur votre serveur IRC, le rendant plus attractif et plus utile pour vos utilisateurs.
|
||||||
|
|
||||||
|
Dans le cadre de notre projet nous utiliserons hexcat comme reference de client irc.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user