mirror of
https://github.com/Ladebeze66/ft_irc.git
synced 2025-12-16 05:58:09 +01:00
startmulticlientok
This commit is contained in:
parent
be09476005
commit
070f446102
96
.vscode/settings.json
vendored
96
.vscode/settings.json
vendored
@ -57,51 +57,53 @@
|
|||||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||||
"C_Cpp_Runner.msvcSecureNoWarnings": false,
|
"C_Cpp_Runner.msvcSecureNoWarnings": false,
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"array": "cpp",
|
"array": "cpp",
|
||||||
"atomic": "cpp",
|
"atomic": "cpp",
|
||||||
"bit": "cpp",
|
"bit": "cpp",
|
||||||
"*.tcc": "cpp",
|
"*.tcc": "cpp",
|
||||||
"cctype": "cpp",
|
"cctype": "cpp",
|
||||||
"clocale": "cpp",
|
"clocale": "cpp",
|
||||||
"cmath": "cpp",
|
"cmath": "cpp",
|
||||||
"compare": "cpp",
|
"compare": "cpp",
|
||||||
"concepts": "cpp",
|
"concepts": "cpp",
|
||||||
"cstdarg": "cpp",
|
"cstdarg": "cpp",
|
||||||
"cstddef": "cpp",
|
"cstddef": "cpp",
|
||||||
"cstdint": "cpp",
|
"cstdint": "cpp",
|
||||||
"cstdio": "cpp",
|
"cstdio": "cpp",
|
||||||
"cstdlib": "cpp",
|
"cstdlib": "cpp",
|
||||||
"cstring": "cpp",
|
"cstring": "cpp",
|
||||||
"cwchar": "cpp",
|
"cwchar": "cpp",
|
||||||
"cwctype": "cpp",
|
"cwctype": "cpp",
|
||||||
"deque": "cpp",
|
"deque": "cpp",
|
||||||
"string": "cpp",
|
"string": "cpp",
|
||||||
"unordered_map": "cpp",
|
"unordered_map": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"exception": "cpp",
|
"exception": "cpp",
|
||||||
"algorithm": "cpp",
|
"algorithm": "cpp",
|
||||||
"functional": "cpp",
|
"functional": "cpp",
|
||||||
"iterator": "cpp",
|
"iterator": "cpp",
|
||||||
"memory": "cpp",
|
"memory": "cpp",
|
||||||
"memory_resource": "cpp",
|
"memory_resource": "cpp",
|
||||||
"numeric": "cpp",
|
"numeric": "cpp",
|
||||||
"random": "cpp",
|
"random": "cpp",
|
||||||
"string_view": "cpp",
|
"string_view": "cpp",
|
||||||
"system_error": "cpp",
|
"system_error": "cpp",
|
||||||
"tuple": "cpp",
|
"tuple": "cpp",
|
||||||
"type_traits": "cpp",
|
"type_traits": "cpp",
|
||||||
"utility": "cpp",
|
"utility": "cpp",
|
||||||
"initializer_list": "cpp",
|
"initializer_list": "cpp",
|
||||||
"iosfwd": "cpp",
|
"iosfwd": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"istream": "cpp",
|
"istream": "cpp",
|
||||||
"limits": "cpp",
|
"limits": "cpp",
|
||||||
"new": "cpp",
|
"new": "cpp",
|
||||||
"numbers": "cpp",
|
"numbers": "cpp",
|
||||||
"ostream": "cpp",
|
"ostream": "cpp",
|
||||||
"sstream": "cpp",
|
"sstream": "cpp",
|
||||||
"stdexcept": "cpp",
|
"stdexcept": "cpp",
|
||||||
"streambuf": "cpp",
|
"streambuf": "cpp",
|
||||||
"typeinfo": "cpp"
|
"typeinfo": "cpp",
|
||||||
}
|
"ctime": "cpp",
|
||||||
|
"map": "cpp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
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:50 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:07:50 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:33:01 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 16:20:58 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -18,6 +18,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
|
||||||
class Channel {
|
class Channel {
|
||||||
public:
|
public:
|
||||||
Channel(const std::string& name);
|
Channel(const std::string& name);
|
||||||
|
|||||||
@ -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/10 14:10:35 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 19:14:26 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -18,10 +18,14 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include "Server.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Client {
|
class Client {
|
||||||
public:
|
public:
|
||||||
Client(int socket, const std::string& nickname, const std::string& username);
|
Client();
|
||||||
|
Client(int socket, const std::string& nickname = "defaultNickName", const std::string& username = "defaultUserName");
|
||||||
~Client();
|
~Client();
|
||||||
|
|
||||||
void sendMessage(const std::string& message);
|
void sendMessage(const std::string& message);
|
||||||
@ -29,13 +33,14 @@ public:
|
|||||||
void setNickname(const std::string& newNickname);
|
void setNickname(const std::string& newNickname);
|
||||||
std::string getNickname() const; // Ajout de la méthode getNickname
|
std::string getNickname() const; // Ajout de la méthode getNickname
|
||||||
int getSocket() const;
|
int getSocket() const;
|
||||||
|
void setUsername(const std::string& newUsername);
|
||||||
|
void setRealname(const std::string& newRealname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int socket;
|
int socket;
|
||||||
std::string nickname; // Assurez-vous que cette donnée membre est accessible via getNickname
|
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:19:30 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:19:30 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:49:16 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/12 17:09:20 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -21,22 +21,25 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
|
||||||
class CommandHandler {
|
class Client;
|
||||||
|
class Channel;
|
||||||
|
|
||||||
|
class CommandHandler
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
CommandHandler();
|
CommandHandler();
|
||||||
~CommandHandler();
|
~CommandHandler();
|
||||||
void handleCommand(const std::string& command, Client* client);
|
void handleCommand(const std::string& commandLine, Client* client);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, Channel*> channels;
|
std::map<std::string, Channel*> channels;
|
||||||
|
std::vector<std::string> split(const std::string& s, char delimiter);
|
||||||
|
|
||||||
void handleJoin(const std::string& command, Client* client);
|
void handleJoin(const std::string& command, Client* client);
|
||||||
void handlePart(const std::string& command, Client* client);
|
void handlePart(const std::string& command, Client* client);
|
||||||
void handleNick(const std::string& command, Client* client);
|
void handleNick(const std::string& command, Client* client);
|
||||||
void handlePrivmsg(const std::string& command, Client* client);
|
void handlePrivmsg(const std::string& command, Client* client);
|
||||||
void handleQuit(Client* client);
|
//void handleQuit(Client* client);
|
||||||
|
|
||||||
std::vector<std::string> split(const std::string& s, char delimiter);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // COMMANDHANDLER_HPP
|
#endif // COMMANDHANDLER_HPP
|
||||||
|
|||||||
@ -6,54 +6,60 @@
|
|||||||
/* 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/10 14:10:44 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/12 17:14:30 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
#ifndef SERVER_HPP
|
#ifndef SERVER_HPP
|
||||||
#define SERVER_HPP
|
#define SERVER_HPP
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <cerrno>
|
||||||
|
#include <cstdio>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sys/socket.h>
|
#include <sstream>
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdexcept>
|
#include <unistd.h>
|
||||||
#include <cerrno>
|
#include <sys/select.h>
|
||||||
#include <pthread.h>
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Client.hpp" // Assurez-vous que Client est inclus avant Server
|
#include "color.hpp"
|
||||||
|
#include "Client.hpp"
|
||||||
#include "CommandHandler.hpp"
|
#include "CommandHandler.hpp"
|
||||||
|
|
||||||
class Server; // Déclaration anticipée de Server si nécessaire
|
class Client;
|
||||||
|
class CommandHandler;
|
||||||
|
|
||||||
// Structure pour passer des données aux threads
|
class Server
|
||||||
struct ClientContext {
|
{
|
||||||
Client* client;
|
|
||||||
Server* server;
|
|
||||||
CommandHandler* cmdHandler;
|
|
||||||
|
|
||||||
ClientContext(Client* c, Server* s, CommandHandler* ch) : client(c), server(s), cmdHandler(ch) {}
|
|
||||||
};
|
|
||||||
class Server {
|
|
||||||
public:
|
public:
|
||||||
Server(int port, const std::string& password);
|
Server(int port, const std::string& password);
|
||||||
~Server();
|
~Server();
|
||||||
bool initialize();
|
void run();
|
||||||
void run();
|
bool initialize();
|
||||||
|
void closeClient(int sockfd);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int listener; // Socket descriptor for the server
|
int port; // Port d'écoute
|
||||||
int port; // Port number to bind the server
|
std::string password; // Mot de passe pour les clients se connectant
|
||||||
std::string password; // Server password for client connections
|
|
||||||
bool running; // Server running status
|
|
||||||
std::vector<pthread_t> threads; // List of threads for client management
|
|
||||||
|
|
||||||
static void *manageClient(void *clientContext); // Static to be compatible with pthread
|
bool running; // État d'exécution du serveur
|
||||||
|
int listener; // Socket d'écoute du serveur
|
||||||
|
int fdmax;
|
||||||
|
fd_set master_set; // Ensemble principal des descripteurs de fichiers pour select
|
||||||
|
std::map<int, Client*> clients; // Mapping de socket à Client
|
||||||
|
std::map<int, CommandHandler*> handlers; // CommandHandler pour chaque client
|
||||||
|
|
||||||
|
void acceptNewClient();
|
||||||
|
bool handleClientActivity(int sockfd);
|
||||||
|
bool getlineFromClient(Client* client, std::string& line);
|
||||||
|
void handleIRCMessages(Client* client, CommandHandler& cmdHandler);
|
||||||
|
bool processInitialCommands(Client* client);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SERVER_HPP
|
#endif // SERVER_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
/* */
|
/* */
|
||||||
/* ::: :::::::: */
|
/* ::: :::::::: */
|
||||||
/* utilities.hpp :+: :+: :+: */
|
/* Utilities.hpp :+: :+: :+: */
|
||||||
/* +:+ +:+ +:+ */
|
/* +:+ +:+ +:+ */
|
||||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
/* +#+#+#+#+#+ +#+ */
|
/* +#+#+#+#+#+ +#+ */
|
||||||
/* Created: 2024/05/09 14:22:54 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:22:54 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:35:04 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 13:34:54 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -22,10 +22,7 @@
|
|||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
// Split a string by a delimiter and return a vector of substrings
|
// Split a string by a delimiter and return a vector of substrings
|
||||||
std::vector<std::string> split(const std::string& s, char delimiter);
|
std::vector<std::string> split(const std::string& str, char delimiter);
|
||||||
|
|
||||||
// Trim whitespace from the start and end of a string
|
|
||||||
std::string trim(const std::string& s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // UTILITIES_HPP
|
#endif // UTILITIES_HPP
|
||||||
|
|||||||
27
ft_irc/include/color.hpp
Normal file
27
ft_irc/include/color.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* color.hpp :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2024/05/12 16:31:27 by fgras-ca #+# #+# */
|
||||||
|
/* Updated: 2024/05/12 16:35:03 by fgras-ca ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
#ifndef COLOR_HPP
|
||||||
|
#define COLOR_HPP
|
||||||
|
|
||||||
|
# define RESET "\033[0m"
|
||||||
|
# define GRAY "\033[0;90m"
|
||||||
|
# define RED "\033[0;91m"
|
||||||
|
# define GREEN "\033[0;92m"
|
||||||
|
# define YELLOW "\033[0;93m"
|
||||||
|
# define BLUE "\033[0;94m"
|
||||||
|
# define MAGENTA "\033[0;95m"
|
||||||
|
# define CYAN "\033[0;96m"
|
||||||
|
# define WHITE "\033[0;97m"
|
||||||
|
# define ORANGE "\033[38;5;214m"
|
||||||
|
|
||||||
|
#endif
|
||||||
BIN
ft_irc/ircserv
BIN
ft_irc/ircserv
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:27 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/10 13:33:20 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 16:11:10 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -14,6 +14,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
Client::Client() {}
|
||||||
|
|
||||||
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) {}
|
||||||
|
|
||||||
@ -57,3 +59,11 @@ int Client::getSocket() const {
|
|||||||
return socket;
|
return socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Client::setUsername(const std::string& newUsername) {
|
||||||
|
nickname = newUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setRealname(const std::string& newRealname) {
|
||||||
|
// Assurez-vous d'avoir un membre `realname` dans Client
|
||||||
|
username = newRealname;
|
||||||
|
}
|
||||||
@ -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/10 12:33:00 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/12 17:11:00 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -14,28 +14,42 @@
|
|||||||
|
|
||||||
CommandHandler::CommandHandler() {}
|
CommandHandler::CommandHandler() {}
|
||||||
|
|
||||||
CommandHandler::~CommandHandler() {
|
CommandHandler::~CommandHandler()
|
||||||
for (std::map<std::string, Channel*>::iterator it = channels.begin(); it != channels.end(); ++it) {
|
{
|
||||||
|
for (std::map<std::string, Channel*>::iterator it = channels.begin(); it != channels.end(); ++it)
|
||||||
|
{
|
||||||
delete it->second;
|
delete it->second;
|
||||||
}
|
}
|
||||||
channels.clear();
|
channels.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::handleCommand(const std::string& command, Client* client) {
|
void CommandHandler::handleCommand(const std::string& commandLine, Client* client)
|
||||||
if (command.find("JOIN ") == 0) {
|
{
|
||||||
handleJoin(command, client);
|
std::istringstream stream(commandLine);
|
||||||
} else if (command.find("PART ") == 0) {
|
std::string command;
|
||||||
handlePart(command, client);
|
stream >> command;
|
||||||
} else if (command.find("NICK ") == 0) {
|
|
||||||
handleNick(command, client);
|
if (command == "JOIN") {
|
||||||
} else if (command.find("PRIVMSG ") == 0) {
|
std::cout << "Commande Join reconnue" << std::endl;
|
||||||
handlePrivmsg(command, client);
|
handleJoin(commandLine, client);
|
||||||
} else if (command == "QUIT") {
|
} else if (command == "PART") {
|
||||||
|
std::cout << "Commande part reconnue" << std::endl;
|
||||||
|
handlePart(commandLine, client);
|
||||||
|
} else if (command == "NICK") {
|
||||||
|
std::cout << "Commande nick reconnue" << std::endl;
|
||||||
|
handleNick(commandLine, client);
|
||||||
|
} else if (command == "PRIVMSG") {
|
||||||
|
std::cout << "Commande privmsg reconnue" << std::endl;
|
||||||
|
handlePrivmsg(commandLine, client);
|
||||||
|
} /*else if (command == "QUIT") {
|
||||||
|
std::cout << "Commande quit reconnue" << std::endl;
|
||||||
handleQuit(client);
|
handleQuit(client);
|
||||||
}
|
}*/
|
||||||
|
// Ajoutez d'autres commandes IRC ici
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::handleJoin(const std::string& command, Client* client) {
|
void CommandHandler::handleJoin(const std::string& command, Client* client) {
|
||||||
|
std::cout << "Lancement fonction Join reconnue" << std::endl;
|
||||||
std::vector<std::string> tokens = split(command, ' ');
|
std::vector<std::string> tokens = split(command, ' ');
|
||||||
if (tokens.size() > 1) {
|
if (tokens.size() > 1) {
|
||||||
std::string channelName = tokens[1];
|
std::string channelName = tokens[1];
|
||||||
@ -78,11 +92,11 @@ void CommandHandler::handlePrivmsg(const std::string& command, Client* client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandHandler::handleQuit(Client* client) {
|
/*void CommandHandler::handleQuit(Client* client) {
|
||||||
for (std::map<std::string, Channel*>::iterator it = channels.begin(); it != channels.end(); ++it) {
|
for (std::map<std::string, Channel*>::iterator it = channels.begin(); it != channels.end(); ++it) {
|
||||||
it->second->removeClient(client);
|
it->second->removeClient(client);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
std::vector<std::string> CommandHandler::split(const std::string& s, char delimiter) {
|
std::vector<std::string> CommandHandler::split(const std::string& s, char delimiter) {
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
|
|||||||
@ -6,115 +6,321 @@
|
|||||||
/* 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/10 14:13:02 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/12 17:07: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)
|
||||||
|
{
|
||||||
|
FD_ZERO(&master_set);
|
||||||
|
std::cout << GREEN << "Server constructed for port: " << RESET << port << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
Server::~Server() {
|
Server::~Server()
|
||||||
for (size_t i = 0; i < threads.size(); ++i) {
|
{
|
||||||
if (threads[i]) pthread_join(threads[i], NULL);
|
std::map<int, Client*>::iterator it;
|
||||||
}
|
for (it = clients.begin(); it != clients.end(); ++it)
|
||||||
close(listener);
|
{
|
||||||
|
delete it->second;
|
||||||
|
close(it->first);
|
||||||
|
}
|
||||||
|
std::map<int, CommandHandler*>::iterator itHandler;
|
||||||
|
for (itHandler = handlers.begin(); itHandler != handlers.end(); ++itHandler)
|
||||||
|
{
|
||||||
|
delete itHandler->second;
|
||||||
|
}
|
||||||
|
std::cout << RED << "Server destroyed, all clients closed." << RESET << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Server::initialize() {
|
bool Server::initialize()
|
||||||
struct sockaddr_in server_addr;
|
{
|
||||||
listener = socket(AF_INET, SOCK_STREAM, 0);
|
struct sockaddr_in server_addr;
|
||||||
if (listener == -1) {
|
listener = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
std::cerr << "Error creating socket: " << strerror(errno) << std::endl;
|
if (listener == -1)
|
||||||
return false;
|
{
|
||||||
}
|
std::cerr << RED << "Error creating socket: " << strerror(errno) << RESET << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&server_addr, 0, sizeof(server_addr));
|
int opt = 1;
|
||||||
server_addr.sin_family = AF_INET;
|
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1)
|
||||||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
{
|
||||||
server_addr.sin_port = htons(port);
|
std::cerr << RED << "Error setting socket options: " << strerror(errno) << RESET << std::endl;
|
||||||
|
close(listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
std::cerr << "Error binding socket: " << strerror(errno) << std::endl;
|
server_addr.sin_family = AF_INET;
|
||||||
close(listener);
|
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
return false;
|
server_addr.sin_port = htons(port);
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(listener, 10) == -1) {
|
if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
|
||||||
std::cerr << "Error listening: " << strerror(errno) << std::endl;
|
{
|
||||||
close(listener);
|
std::cerr << RED << "Error binding socket: " << strerror(errno) << RESET << std::endl;
|
||||||
return false;
|
close(listener);
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "Server initialized and listening on port " << port << std::endl;
|
if (listen(listener, 10) == -1)
|
||||||
running = true;
|
{
|
||||||
return true;
|
std::cerr << RED << "Error listening: " << strerror(errno) << RESET << std::endl;
|
||||||
|
close(listener);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_SET(listener, &master_set);
|
||||||
|
fdmax = listener; // Set the initial max file descriptor to listener
|
||||||
|
running = true;
|
||||||
|
|
||||||
|
std::cout << GREEN << "Server initialized and listening on port: " << RESET << port << std::endl;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::run() {
|
bool Server::getlineFromClient(Client* client, std::string& line)
|
||||||
if (!running) {
|
{
|
||||||
std::cerr << "Server not initialized or already running." << std::endl;
|
char buffer[1024];
|
||||||
return;
|
memset(buffer, 0, sizeof(buffer));
|
||||||
}
|
int len = recv(client->getSocket(), buffer, sizeof(buffer) - 1, 0);
|
||||||
|
|
||||||
CommandHandler cmdHandler;
|
if (len > 0)
|
||||||
while (running) {
|
{
|
||||||
struct sockaddr_in client_addr;
|
buffer[len] = '\0'; // Ensure null termination
|
||||||
socklen_t client_len = sizeof(client_addr);
|
line = std::string(buffer);
|
||||||
int client_sock = accept(listener, (struct sockaddr *)&client_addr, &client_len);
|
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
||||||
if (client_sock == -1) {
|
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
|
||||||
std::cerr << "Error accepting connection: " << strerror(errno) << std::endl;
|
return true;
|
||||||
continue;
|
}
|
||||||
}
|
else if (len == 0)
|
||||||
|
{
|
||||||
Client* newClient = new Client(client_sock, "DefaultNickname", "DefaultUsername");
|
std::cout << RED << "Client disconnected." << RESET << std::endl;
|
||||||
ClientContext* context = new ClientContext(newClient, this, &cmdHandler);
|
return false; // Connection is closed
|
||||||
pthread_t thread;
|
}
|
||||||
pthread_create(&thread, NULL, &Server::manageClient, context);
|
else
|
||||||
pthread_detach(thread);
|
{
|
||||||
threads.push_back(thread);
|
std::cerr << RED << "Error reading from client socket: " << strerror(errno) << RESET << std::endl;
|
||||||
}
|
return false; // An error occurred
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Server::manageClient(void *clientContext) {
|
bool Server::processInitialCommands(Client* client)
|
||||||
ClientContext* ctx = static_cast<ClientContext*>(clientContext);
|
{
|
||||||
Client* client = ctx->client;
|
std::string line;
|
||||||
Server* server = ctx->server;
|
bool isAuthenticated = false; // Pour garder une trace de l'authentification
|
||||||
|
|
||||||
client->sendMessage("Welcome to the IRC Server!\n");
|
while (getlineFromClient(client, line) && !line.empty())
|
||||||
client->sendMessage("Password required:\n");
|
{
|
||||||
|
std::cout << MAGENTA << "Processing line: " << RESET << line << std::endl;
|
||||||
|
// Extraction et traitement de la commande PASS
|
||||||
|
size_t passEnd = line.find("NICK");
|
||||||
|
if (passEnd != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string passCommand = line.substr(0, passEnd);
|
||||||
|
std::istringstream passIss(passCommand);
|
||||||
|
std::string passToken, extractedPassword;
|
||||||
|
passIss >> passToken >> extractedPassword;
|
||||||
|
if (extractedPassword != this->password)
|
||||||
|
{
|
||||||
|
client->sendMessage("ERROR :Wrong password\r\n");
|
||||||
|
std::cout << RED << "Authentication failed for password: " << RESET << extractedPassword << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "CLIENT Socket: " << client->getSocket() << GREEN << " :Authentication successful." << RESET << std::endl;
|
||||||
|
isAuthenticated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string passwordInput = client->receiveMessage();
|
// Traitement des commandes NICK et USER
|
||||||
std::cout << "Received password: [" << passwordInput << "]" << std::endl;
|
if (isAuthenticated)
|
||||||
|
{ // Seulement si authentifié
|
||||||
if (passwordInput != server->password) {
|
size_t nickEnd = line.find("USER");
|
||||||
client->sendMessage("Incorrect password.\n");
|
if (nickEnd != std::string::npos)
|
||||||
std::cout << "Password mismatch." << std::endl;
|
{
|
||||||
close(client->getSocket());
|
std::string nickCommand = line.substr(passEnd, nickEnd - passEnd);
|
||||||
delete client;
|
std::istringstream nickIss(nickCommand);
|
||||||
delete ctx;
|
std::string nickToken, nickname;
|
||||||
return NULL;
|
nickIss >> nickToken >> nickname;
|
||||||
}
|
client->setNickname(nickname);
|
||||||
|
std::cout << BLUE << "NickName SET: " << RESET << nickname << std::endl;
|
||||||
client->sendMessage("Password correct.\n");
|
std::string userCommand = line.substr(nickEnd);
|
||||||
|
std::istringstream userIss(userCommand);
|
||||||
std::string command;
|
std::string userToken, username, realname;
|
||||||
while ((command = client->receiveMessage()) != "") {
|
userIss >> userToken >> username;
|
||||||
ctx->cmdHandler->handleCommand(command, client);
|
size_t realnameStart = userCommand.find(":");
|
||||||
if (command == "QUIT") break;
|
if (realnameStart != std::string::npos)
|
||||||
}
|
{
|
||||||
|
realname = userCommand.substr(realnameStart + 1);
|
||||||
close(client->getSocket());
|
client->setUsername(username);
|
||||||
delete client;
|
client->setRealname(realname);
|
||||||
delete ctx;
|
std::cout << GREEN << "CLIENT: " << "SET NickName: " << nickname << "; UserName: " << username << "; Socket: " << client->getSocket() << RESET << std::endl;
|
||||||
return NULL;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Après une authentification réussie, passez à la gestion des messages IRC
|
||||||
|
if (isAuthenticated)
|
||||||
|
{
|
||||||
|
handleIRCMessages(client, *new CommandHandler()); // Attention à la gestion de la mémoire ici
|
||||||
|
}
|
||||||
|
return isAuthenticated;
|
||||||
|
}
|
||||||
|
// Handle IRC commands
|
||||||
|
void Server::handleIRCMessages(Client* client, CommandHandler& cmdHandler)
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
while (getlineFromClient(client, line) && !line.empty())
|
||||||
|
{
|
||||||
|
std::cout << YELLOW << "Handling IRC message: " << RESET << line << std::endl;
|
||||||
|
cmdHandler.handleCommand(line, client);
|
||||||
|
if (line.find("QUIT") != std::string::npos)
|
||||||
|
{
|
||||||
|
std::cout << RED << "Client Socket (" << client->getSocket() << ") requested to quit." << RESET << std::endl;
|
||||||
|
closeClient(client->getSocket()); // Assuming you have a method to close clients
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::run()
|
||||||
|
{
|
||||||
|
fd_set read_fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
|
||||||
|
if (!initialize())
|
||||||
|
{
|
||||||
|
std::cerr << RED << "Server initialization failed. Exiting..." << RESET << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << GREEN << "Server is running on port: " << RESET << port << std::endl;
|
||||||
|
while (running)
|
||||||
|
{
|
||||||
|
FD_ZERO(&read_fds);
|
||||||
|
FD_SET(listener, &read_fds);
|
||||||
|
std::map<int, Client*>::iterator it;
|
||||||
|
for (it = clients.begin(); it != clients.end(); ++it)
|
||||||
|
{
|
||||||
|
FD_SET(it->first, &read_fds);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout.tv_sec = 5;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
|
std::cout << ORANGE << "Waiting for select..." << RESET << std::endl;
|
||||||
|
int selectResult = select(fdmax + 1, &read_fds, NULL, NULL, &timeout);
|
||||||
|
|
||||||
|
if (selectResult == -1)
|
||||||
|
{
|
||||||
|
perror("Select error");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (selectResult == 0)
|
||||||
|
{
|
||||||
|
std::cout << GRAY << "Select timeout occurred, no activity." << RESET << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FD_ISSET(listener, &read_fds))
|
||||||
|
{
|
||||||
|
acceptNewClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i <= fdmax; i++)
|
||||||
|
{
|
||||||
|
if (i != listener && FD_ISSET(i, &read_fds))
|
||||||
|
{
|
||||||
|
if (!handleClientActivity(i))
|
||||||
|
{
|
||||||
|
closeClient(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::acceptNewClient()
|
||||||
|
{
|
||||||
|
struct sockaddr_in client_addr;
|
||||||
|
socklen_t addrlen = sizeof(client_addr);
|
||||||
|
std::cout << CYAN << "Ready to accept new connection..." << RESET << std::endl;
|
||||||
|
int newfd = accept(listener, (struct sockaddr *)&client_addr, &addrlen);
|
||||||
|
|
||||||
|
if (newfd == -1)
|
||||||
|
{
|
||||||
|
perror("Accept failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients[newfd] = new Client(newfd);
|
||||||
|
FD_SET(newfd, &master_set);
|
||||||
|
if (newfd > fdmax)
|
||||||
|
{
|
||||||
|
fdmax = newfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << GREEN << "Accepted new client: " << inet_ntoa(client_addr.sin_addr) << " on fd: " << newfd << RESET << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::handleClientActivity(int sockfd)
|
||||||
|
{
|
||||||
|
Client* client = clients[sockfd];
|
||||||
|
if (!client)
|
||||||
|
{
|
||||||
|
std::cerr << RED << "Client not found for socket " << RESET << sockfd << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
if (getlineFromClient(client, line) && !line.empty())
|
||||||
|
{
|
||||||
|
std::cout << GREEN << "Received message: [" << line << "]" << RESET << std::endl;
|
||||||
|
CommandHandler* cmdHandler = handlers[sockfd];
|
||||||
|
cmdHandler->handleCommand(line, client);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << RED << "Client disconnected or error on socket: " << RESET << sockfd << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::closeClient(int sockfd)
|
||||||
|
{
|
||||||
|
std::map<int, Client*>::iterator it = clients.find(sockfd);
|
||||||
|
if (it != clients.end())
|
||||||
|
{
|
||||||
|
delete it->second;
|
||||||
|
clients.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<int, CommandHandler*>::iterator handlerIt = handlers.find(sockfd);
|
||||||
|
if (handlerIt != handlers.end())
|
||||||
|
{
|
||||||
|
delete handlerIt->second;
|
||||||
|
handlers.erase(handlerIt);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(sockfd); // Close the socket
|
||||||
|
FD_CLR(sockfd, &master_set); // Remove from the master set
|
||||||
|
|
||||||
|
// Recalculate fdmax
|
||||||
|
if (sockfd == fdmax)
|
||||||
|
{
|
||||||
|
fdmax = listener; // Reset fdmax to the listener's socket
|
||||||
|
for (it = clients.begin(); it != clients.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->first > fdmax)
|
||||||
|
{
|
||||||
|
fdmax = it->first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << RED << "Closed client on socket: " << RESET << sockfd << std::endl;
|
||||||
|
}
|
||||||
|
|||||||
@ -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:00:46 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:00:46 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:00:52 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 17:16:28 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -21,11 +21,7 @@ int main(int argc, char* argv[]) {
|
|||||||
std::string password = argv[2];
|
std::string password = argv[2];
|
||||||
|
|
||||||
Server ircServer(port, password);
|
Server ircServer(port, password);
|
||||||
if (!ircServer.initialize()) {
|
ircServer.run(); // initialize() sera appelée au début de run()
|
||||||
std::cerr << "Failed to initialize server." << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ircServer.run();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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:23:12 by fgras-ca #+# #+# */
|
/* Created: 2024/05/09 14:23:12 by fgras-ca #+# #+# */
|
||||||
/* Updated: 2024/05/09 14:34:50 by fgras-ca ### ########.fr */
|
/* Updated: 2024/05/11 13:35:49 by fgras-ca ### ########.fr */
|
||||||
/* */
|
/* */
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
@ -14,22 +14,14 @@
|
|||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
|
|
||||||
std::vector<std::string> split(const std::string& s, char delimiter) {
|
std::vector<std::string> split(const std::string& str, char delimiter) {
|
||||||
std::vector<std::string> tokens;
|
std::vector<std::string> tokens;
|
||||||
|
std::stringstream ss(str);
|
||||||
std::string token;
|
std::string token;
|
||||||
std::istringstream tokenStream(s);
|
while (getline(ss, token, delimiter)) {
|
||||||
while (std::getline(tokenStream, token, delimiter)) {
|
tokens.push_back(token);
|
||||||
tokens.push_back(trim(token));
|
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string trim(const std::string& str) {
|
|
||||||
size_t first = str.find_first_not_of(' ');
|
|
||||||
if (first == std::string::npos)
|
|
||||||
return "";
|
|
||||||
size_t last = str.find_last_not_of(' ');
|
|
||||||
return str.substr(first, (last - first + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user