changed project structure
This commit is contained in:
80
Includes/Macros.hpp
Normal file
80
Includes/Macros.hpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef MACROS_HPP
|
||||
#define MACROS_HPP
|
||||
|
||||
#define OO1 ":irc.l9oroch 001 " + nickname + " :Welcome to the MiniChat Network, " + nickname + '\n'
|
||||
#define OO2 ":irc.l9oroch 002 " + nickname + " :Your host is MiniChat, running version 4.5" + '\n'
|
||||
#define OO3 ":irc.l9oroch 003 " + nickname + " :This server was created " + formatCreationTime() + '\n'
|
||||
#define OO4 ":irc.l9oroch 004 " + nickname + " MiniChat MiniChat(enterprise)-2.3(12)-netty(5.4c)-proxy(0.9) MiniChat" + '\n'
|
||||
|
||||
#define JOIN_MESSAGE(nickname, channelName) (":" + nickname + " JOIN #" + channelName + "\n")
|
||||
#define MODE_MESSAGE(channelName) (":irc.l9oroch MODE #" + channelName + " +nt\n")
|
||||
#define NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 353 " + nickname + " = #" + channelName + " :@" + nickname + "\n")
|
||||
#define NAMES_MESSAGE2(nickname, channelName) (":irc.l9oroch 353 " + nickname + " @ #" + channelName + " :")
|
||||
#define END_OF_NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 366 " + nickname + " #" + channelName + " :End of /NAMES list.\n")
|
||||
#define CHANNEL_MESSAGE(channelName, creationTimeMessage) (":irc.l9oroch 354 " + channelName + " " + creationTimeMessage + "\n")
|
||||
#define TOPIC_MESSAGE(nickname, channelName, topic) (":irc.l9oroch 332 " + nickname + " #" + channelName + " :" + topic + " https://irc.com\n")
|
||||
#define TOPIC_MESSAGE2(nicknamesender, channelname, topic) (":" + nicknamesender + " TOPIC #" + channelname + " :" + topic + "\n")
|
||||
|
||||
#define PRIVATE_MESSAGE(senderFd, recipient, message) (":" + nicknames[senderFd] + " PRIVMSG " + recipient + " :" + message + "\r\n")
|
||||
#define ERROR_MESSAGE(senderFd, recipient) (":server.host NOTICE " + nicknames[senderFd] + " :Error: User '" + recipient + "' not found or offline\r\n")
|
||||
#define INVITE_MESSAGE(senderFd, recipient, channelName) (":" + nicknames[senderFd] + " INVITE " + recipient + " :#" + channelName + "\r\n")
|
||||
#define KICK_MESSAGE(nicknamesender, channelname, usertokick, reason) (":" + nicknamesender + " KICK #" + channelname + " " + usertokick + " :" + reason + "\n")
|
||||
#define KICK_MESSAGE2(channelName, fd, userToKick, reason) (":" + channels[channelName].getNickname(fd) + " KICK #" + channelName + " " + userToKick + " :" + reason + "\n")
|
||||
|
||||
#define MODE_CHANGE_MESSAGE(channelname, mode, sender, receiver) \
|
||||
(mode == "+t" ? MODE_CHANGE_T(channelname, sender) : \
|
||||
(mode == "-t" ? MODE_CHANGE_MINUS_T(channelname, sender) : \
|
||||
(mode == "+o" ? MODE_CHANGE_O(channelname, sender, mode, receiver) : \
|
||||
(mode == "-o" ? MODE_CHANGE_MINUS_O(channelname, sender, mode, receiver) : \
|
||||
(mode == "+i" ? MODE_CHANGE_IK(channelname, sender, mode) : \
|
||||
(mode == "-i" ? MODE_CHANGE_IK(channelname, sender, mode) : \
|
||||
(mode == "+k" ? MODE_CHANGE_IK(channelname, sender, mode) : \
|
||||
(mode == "-k" ? MODE_CHANGE_IK(channelname, sender, mode) : \
|
||||
(mode == "+l" ? MODE_CHANGE_L(channelname, sender, mode) : \
|
||||
(mode == "-l" ? MODE_CHANGE_L(channelname, sender, mode) : ""))))))))))
|
||||
|
||||
#define MODE_CHANGE_T(channelname, sender) (MODE_CHANGE_MINUS_T(channelname, sender))
|
||||
#define MODE_CHANGE_MINUS_T(channelname, sender) (":server.host MODE #" + channelname + " -t by " + sender + "\n")
|
||||
#define MODE_CHANGE_O(channelname, sender, mode, receiver) (":server.host MODE #" + channelname + " " + mode + " by " + sender + " and set " + receiver + "as operator\n")
|
||||
#define MODE_CHANGE_MINUS_O(channelname, sender, mode, receiver) (":server.host MODE #" + channelname + " " + mode + " by " + sender + " and unset " + receiver + "as operator\n")
|
||||
#define MODE_CHANGE_IK(channelname, sender, mode) (":server.host MODE #" + channelname + " " + mode + " by " + sender + "\n")
|
||||
#define MODE_CHANGE_L(channelname, sender, mode) (":server.host MODE #" + channelname + " " + mode + " by " + sender + "\n")
|
||||
|
||||
#define ERROR_MESSAGE2(nick) (":server.host NOTICE " + nick + what)
|
||||
#define ERROR_MESSAGE3(sender, channelName, userToKick) (":" + sender + " PRIVMSG #" + channelName + " :Error: the user : " + userToKick + " is not found or offline.\r\n")
|
||||
#define ERROR_MESSAGE4(sender, channelName, userToKick) (":" + sender + " PRIVMSG #" + channelName + " :Error1: You are not authorized to execute this command " + userToKick + "\r\n")
|
||||
#define ERROR_MESSAGE5() (":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command " + "\r\n")
|
||||
#define ERROR_MESSAGE6(sender, channelName) (":" + sender + " PRIVMSG #" + channelName + " :Error2: You are not authorized to execute this command\r\n")
|
||||
#define ERROR_MESSAGE7(channelName, fd) (":" + channels[channelName].getNickname(fd) + " PRIVMSG #" + channelName + " :Error: You are not authorized to execute this command\r\n")
|
||||
|
||||
#define CONGRATS_MSG(guessed) (":server.host PRIVMSG #:Congratulations ,you have guessed the number : " + guessed + " correctly\n")
|
||||
#define GUESS_AGAIN(random) (":server.host PRIVMSG #:Sorry ,the correct one is : " + random + "\n")
|
||||
#define GUESS_ERROR() (":server.host PRIVMSG # :Error: Invalid range or guess\n")
|
||||
#define MODE_SET_MESSAGE(channelName, mode, fd, nick) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and set " + nick + "as operator\n")
|
||||
#define MODE_UNSET_MESSAGE(channelName, mode, fd, nick) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + " and unset " + nick + "as operator\n")
|
||||
#define TOPIC_CHANGE_MESSAGE(channelName, mode, fd) (":server.host MODE #" + channelName + " " + mode + " by " + channels[channelName].getNickname(fd) + "\n")
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define CYAN "\033[36m"
|
||||
#define RESET "\033[0m"
|
||||
|
||||
#define MINICHAT "\n$$\\ $$\\ $$\\ $$\\ $$$$$$\\ $$\\ $$\\ \n" \
|
||||
"$$$\\ $$$ |\\__| \\__|$$ __$$\\ $$ | $$ | \n" \
|
||||
"$$$$\\ $$$$ |$$\\ $$$$$$$\\ $$\\ $$ / \\__|$$$$$$$\\ $$$$$$\\ $$$$$$\\ \n" \
|
||||
"$$\\$$\\$$ $$ |$$ |$$ __$$\\ $$ |$$ | $$ __$$\\ \\____$$\\_$$ _| \n" \
|
||||
"$$ \\$$$ $$ |$$ |$$ | $$ |$$ |$$ | $$ | $$ | $$$$$$$ | $$ | \n" \
|
||||
"$$ |\\$ /$$ |$$ |$$ | $$ |$$ |$$ | $$\\ $$ | $$ |$$ __$$ | $$ |$$\\ \n" \
|
||||
"$$ | \\_/ $$ |$$ |$$ | $$ |$$ |\\$$$$$$ |$$ | $$ |\\$$$$$$$ | \\$$$$ |\n" \
|
||||
"\\__| \\__|\\__|\\__| \\__|\\__| \\______/ \\__| \\__| \\_______| \\____/ \n\n"
|
||||
|
||||
extern int opperatorfd;
|
||||
extern int issettop;
|
||||
extern int isinvited;
|
||||
extern int itHasPass;
|
||||
extern int channelLimit;
|
||||
extern int limitchannelforincrement;
|
||||
extern int abaaba;
|
||||
|
||||
#endif
|
@@ -20,6 +20,7 @@
|
||||
#include <ctime>
|
||||
#include <ctime>
|
||||
#include <iomanip>
|
||||
#include "Macros.hpp"
|
||||
|
||||
class Server {
|
||||
private:
|
||||
@@ -53,13 +54,19 @@ class Server {
|
||||
void handleInvitation(int senderFd, const std::string& recipient, std::string channelName);
|
||||
|
||||
void broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg);
|
||||
void smallbroadcastMessagefortheckick(std::string nicknamesender , const std::string& channelname, const std::string& usertokick, const std::string& reason);
|
||||
void smallBroadcastMsgForKick(std::string nicknamesender , const std::string& channelname, const std::string& usertokick, const std::string& reason);
|
||||
void smallbroadcastMessageforjoin(std::string nicknamesender , const std::string& channelname);
|
||||
void smallbroadcastMessageforTopic(std::string nicknamesender, const std::string& channelname, std::string topic);
|
||||
void smallbroadcastMOOD(std::string nicknamesender, const std::string& channelname, std::string mode, std::string receiver);
|
||||
int findUserFd1(const std::string& username);
|
||||
bool dontputthesamenick(const std::string& nickname);
|
||||
bool dontputthesameusername(const std::string& username);
|
||||
std::string intToString(int number);
|
||||
std::string trim(const std::string& str);
|
||||
bool startsWith(const std::string& str, const std::string& prefix);
|
||||
int stringToInt(const std::string& str);
|
||||
bool isValidPassword(const std::string& passwordLine);
|
||||
int randomInRange(int min, int max);
|
||||
|
||||
// Server
|
||||
void init();
|
||||
@@ -103,7 +110,4 @@ class Server {
|
||||
void handleChannelLimit(const std::string& nick, const std::string& channelName, const std::string& mode, int fd);
|
||||
};
|
||||
|
||||
int randomInRange(int min, int max);
|
||||
std::string intToString(int number);
|
||||
|
||||
#endif
|
37
Macros.hpp
37
Macros.hpp
@@ -1,37 +0,0 @@
|
||||
#ifndef MACROS_HPP
|
||||
#define MACROS_HPP
|
||||
|
||||
#define OO1 ":irc.l9oroch 001 " + nickname + " :Welcome to the MiniChat Network, " + nickname + '\n'
|
||||
#define OO2 ":irc.l9oroch 002 " + nickname + " :Your host is MiniChat, running version 4.5" + '\n'
|
||||
#define OO3 ":irc.l9oroch 003 " + nickname + " :This server was created " + formatCreationTime() + '\n'
|
||||
#define OO4 ":irc.l9oroch 004 " + nickname + " MiniChat MiniChat(enterprise)-2.3(12)-netty(5.4c)-proxy(0.9) MiniChat" + '\n'
|
||||
|
||||
#define JOIN_MESSAGE(nickname, channelName) (":" + nickname + " JOIN #" + channelName + "\n")
|
||||
#define MODE_MESSAGE(channelName) (":irc.l9oroch MODE #" + channelName + " +nt\n")
|
||||
#define NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 353 " + nickname + " = #" + channelName + " :@" + nickname + "\n")
|
||||
#define NAMES_MESSAGE2(nickname, channelName) (":irc.l9oroch 353 " + nickname + " @ #" + channelName + " :")
|
||||
#define END_OF_NAMES_MESSAGE(nickname, channelName) (":irc.l9oroch 366 " + nickname + " #" + channelName + " :End of /NAMES list.\n")
|
||||
#define CHANNEL_MESSAGE(channelName, creationTimeMessage) (":irc.l9oroch 354 " + channelName + " " + creationTimeMessage + "\n")
|
||||
#define TOPIC_MESSAGE(nickname, channelName, topic) (":irc.l9oroch 332 " + nickname + " #" + channelName + " :" + topic + " https://irc.com\n")
|
||||
#define PRIVATE_MESSAGE(senderFd, recipient, message) (":" + nicknames[senderFd] + " PRIVMSG " + recipient + " :" + message + "\r\n")
|
||||
#define ERROR_MESSAGE(senderFd, recipient) (":server.host NOTICE " + nicknames[senderFd] + " :Error: User '" + recipient + "' not found or offline\r\n")
|
||||
|
||||
|
||||
|
||||
#define BUFFER_SIZE 1024
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define CYAN "\033[36m"
|
||||
#define RESET "\033[0m"
|
||||
|
||||
#define MINICHAT "\n$$\\ $$\\ $$\\ $$\\ $$$$$$\\ $$\\ $$\\ \n" \
|
||||
"$$$\\ $$$ |\\__| \\__|$$ __$$\\ $$ | $$ | \n" \
|
||||
"$$$$\\ $$$$ |$$\\ $$$$$$$\\ $$\\ $$ / \\__|$$$$$$$\\ $$$$$$\\ $$$$$$\\ \n" \
|
||||
"$$\\$$\\$$ $$ |$$ |$$ __$$\\ $$ |$$ | $$ __$$\\ \\____$$\\_$$ _| \n" \
|
||||
"$$ \\$$$ $$ |$$ |$$ | $$ |$$ |$$ | $$ | $$ | $$$$$$$ | $$ | \n" \
|
||||
"$$ |\\$ /$$ |$$ |$$ | $$ |$$ |$$ | $$\\ $$ | $$ |$$ __$$ | $$ |$$\\ \n" \
|
||||
"$$ | \\_/ $$ |$$ |$$ | $$ |$$ |\\$$$$$$ |$$ | $$ |\\$$$$$$$ | \\$$$$ |\n" \
|
||||
"\\__| \\__|\\__|\\__| \\__|\\__| \\______/ \\__| \\__| \\_______| \\____/ \n\n"
|
||||
|
||||
|
||||
#endif
|
5
Makefile
5
Makefile
@@ -1,12 +1,13 @@
|
||||
NAME = ircserv
|
||||
|
||||
SRC = main.cpp Server.cpp Client.cpp Channel.cpp
|
||||
SRC = main.cpp ./Srcs/Server.cpp ./Srcs/Client.cpp ./Srcs/Channel.cpp ./Srcs/Authentication.cpp \
|
||||
./Srcs/Broadcast.cpp ./Srcs/Commands.cpp ./Srcs/Helpers.cpp ./Srcs/Modes.cpp
|
||||
|
||||
OBJ = ${SRC:.cpp=.o}
|
||||
|
||||
CXX = c++
|
||||
|
||||
CXXFLAGS = -std=c++98 -fsanitize=address -g3 -Wall -Wextra -Werror
|
||||
CXXFLAGS = -std=c++98 -fsanitize=address -g3 -Wall -Wextra -Werror -I ./Includes
|
||||
|
||||
all : $(NAME)
|
||||
|
||||
|
1164
Server.cpp
1164
Server.cpp
File diff suppressed because it is too large
Load Diff
110
Srcs/Authentication.cpp
Normal file
110
Srcs/Authentication.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
void Server::processPassword(Client& client, const std::string& command, int fd) {
|
||||
std::string passwordLine = command.substr(command.find(" ") + 1);
|
||||
passwordLine = trim(passwordLine);
|
||||
|
||||
if (isValidPassword(passwordLine)) {
|
||||
passwordLine = passwordLine.substr(1, passwordLine.size() - 2);
|
||||
}
|
||||
|
||||
if (passwordLine.empty()) {
|
||||
std::string errorMessage = "Error: Password cannot be empty\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string serverPassword = getPassowrd();
|
||||
if (serverPassword != passwordLine) {
|
||||
std::string errorMessage = "Error: Incorrect Password\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
} else {
|
||||
std::string confirmation = "Please Enter Your Nickname : \n";
|
||||
send(fd, confirmation.c_str(), confirmation.length(), 0);
|
||||
client.setAuthentication(1);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processNickCmd(Client& client, const std::string& command, int fd) {
|
||||
std::string cmd, nick;
|
||||
std::istringstream iss(command);
|
||||
iss >> cmd >> nick;
|
||||
nick = trim(nick);
|
||||
|
||||
// Check if there are more tokens after the nickname
|
||||
std::string remaining;
|
||||
if (iss >> remaining) {
|
||||
std::string errorMessage = "Error: Command requires only 1 parameter\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the nickname
|
||||
if (dontputthesamenick(nick)) {
|
||||
std::string confirmation = "Please Use a Different Nickname : \n";
|
||||
send(fd, confirmation.c_str(), confirmation.length(), 0);
|
||||
}
|
||||
else {
|
||||
setNickname(fd, nick);
|
||||
for (size_t i = 0; i < _clients.size(); ++i)
|
||||
{
|
||||
if (_clients[i].getFd() == fd) {
|
||||
_clients[i].setNick(nick);
|
||||
std::cout << "Nickname set for client " << fd << ": " << nick << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string confirmation = "Please Enter Your Username : \n";
|
||||
send(fd, confirmation.c_str(), confirmation.length(), 0);
|
||||
client.setAuthentication(2);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processUserCmd(Client& client, const std::string& command, int fd)
|
||||
{
|
||||
std::istringstream iss(command);
|
||||
std::string cmd, username, dontworry, dontworry1, realname, nickname;
|
||||
iss >> cmd >> username >> dontworry >> dontworry1 >> realname;
|
||||
username = trim(username);
|
||||
dontworry = trim(dontworry);
|
||||
dontworry1 = trim(dontworry1);
|
||||
realname = trim(realname);
|
||||
|
||||
std::string reme;
|
||||
if (iss.fail() || iss >> reme) {
|
||||
std::string errorMessage = "Error: Command requires four parameters\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
if (dontputthesameusername(username) == true) {
|
||||
std::string confirmation = "Please Use a Different username : \n";
|
||||
send(fd, confirmation.c_str(), confirmation.length(), 0);
|
||||
}
|
||||
else {
|
||||
setUsernames(fd, username);
|
||||
for (size_t i = 0; i < _clients.size(); ++i) {
|
||||
if (_clients[i].getFd() == fd) {
|
||||
_clients[i].setUser(username);
|
||||
_clients[i].setName(realname);
|
||||
nickname = _clients[i].getNick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
welcome(nickname, fd);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::welcome(const std::string& nickname, int fd){
|
||||
std::string one = OO1;
|
||||
std::string two = OO2;
|
||||
std::string tre = OO3;
|
||||
std::string foor = OO4;
|
||||
send(fd, one.c_str(), one.length(), 0);
|
||||
send(fd, two.c_str(), two.length(), 0);
|
||||
send(fd, tre.c_str(), tre.length(), 0);
|
||||
send(fd, foor.c_str(), foor.length(), 0);
|
||||
}
|
BIN
Srcs/Authentication.o
Normal file
BIN
Srcs/Authentication.o
Normal file
Binary file not shown.
132
Srcs/Broadcast.cpp
Normal file
132
Srcs/Broadcast.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
// brodcasting msg to all nicks in the channel
|
||||
void Server::broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg) {
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channel);
|
||||
if (it == channels.end()) {
|
||||
std::cerr << "Channel " << channel << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
if (channels[channel].findUserFdForKickRegulars(senderNickname) == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string message = ":" + senderNickname + " PRIVMSG #" + channel + " :" + msg + "\r\n";
|
||||
const std::vector<std::string>& clients = it->second.getClients();
|
||||
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& client = clients[i];
|
||||
|
||||
if (client == senderNickname) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int recipientFd = it->second.getUserFd(client);
|
||||
|
||||
if (recipientFd != -1) {
|
||||
std::cout << message << std::endl;
|
||||
send(recipientFd, message.c_str(), message.size(), 0);
|
||||
} else {
|
||||
std::cerr << "Client " << client << " not found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::smallBroadcastMsgForKick(std::string sender , const std::string& channelname, const std::string& usertokick, const std::string& reason) {
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelname);
|
||||
if (it == channels.end()) {
|
||||
std::cerr << "Channel " << channelname << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::string kickMessage = KICK_MESSAGE(sender, channelname, usertokick, reason);
|
||||
|
||||
const std::vector<std::string>& clients = it->second.getClients();
|
||||
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& client = clients[i];
|
||||
|
||||
if (client == sender) {
|
||||
continue;
|
||||
}
|
||||
int recipientFd = it->second.getUserFd(client);
|
||||
if (recipientFd != -1) {
|
||||
send(recipientFd, kickMessage.c_str(), kickMessage.size(), 0);
|
||||
} else {
|
||||
std::cerr << "Client " << client << " not found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::smallbroadcastMessageforjoin(std::string nickname , const std::string& channelName) {
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelName);
|
||||
if (it == channels.end()) {
|
||||
std::cerr << "Channel " << channelName << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::string joinMessage = JOIN_MESSAGE(nickname, channelName);
|
||||
const std::vector<std::string>& clients = it->second.getClients();
|
||||
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& client = clients[i];
|
||||
|
||||
if (client == nickname) {
|
||||
continue;
|
||||
}
|
||||
int recipientFd = it->second.getUserFd(client);
|
||||
if (recipientFd != -1) {
|
||||
send(recipientFd, joinMessage.c_str(), joinMessage.size(), 0);
|
||||
} else {
|
||||
std::cerr << "Client " << client << " not found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::smallbroadcastMessageforTopic(std::string nicknamesender, const std::string& channelname, std::string topic) {
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelname);
|
||||
if (it == channels.end()) {
|
||||
std::cerr << "Channel " << channelname << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string topicMessage = TOPIC_MESSAGE2(nicknamesender, channelname, topic);
|
||||
const std::vector<std::string>& clients = it->second.getClients();
|
||||
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& client = clients[i];
|
||||
|
||||
if (client == nicknamesender) {
|
||||
continue;
|
||||
}
|
||||
int recipientFd = it->second.getUserFd(client);
|
||||
if (recipientFd != -1) {
|
||||
send(recipientFd, topicMessage.c_str(), topicMessage.size(), 0);
|
||||
} else {
|
||||
std::cerr << "Client " << client << " not found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::smallbroadcastMOOD(std::string sender, const std::string& channelname, std::string mode, std::string receiver) {
|
||||
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelname);
|
||||
if (it == channels.end()) {
|
||||
std::cerr << "Channel " << channelname << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::string modeChangeMessage = MODE_CHANGE_MESSAGE(channelname, mode, sender, receiver);
|
||||
|
||||
int senderFd = it->second.getUserFd(sender);
|
||||
const std::vector<std::string>& clients = it->second.getClients();
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& client = clients[i];
|
||||
|
||||
int recipientFd = it->second.getUserFd(client);
|
||||
if (recipientFd != -1 && recipientFd != senderFd) {
|
||||
send(recipientFd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
} else {
|
||||
std::cerr << "Client " << client << " not found or is the sender" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
BIN
Srcs/Broadcast.o
Normal file
BIN
Srcs/Broadcast.o
Normal file
Binary file not shown.
@@ -1,4 +1,5 @@
|
||||
#include "Channel.hpp"
|
||||
#include "Server.hpp"
|
||||
|
||||
Channel::Channel(){}
|
||||
|
||||
@@ -134,3 +135,44 @@ void Channel::removeOperator(const std::string& operatorName )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::createChannel(const std::string& channelName, const std::string& nickname, int fd) {
|
||||
// Check if the channel already exists
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelName);
|
||||
if (it == channels.end()) {
|
||||
isinvited = 0;
|
||||
// Channel doesn't exist, so create it and add the user
|
||||
addUserToChannel(nickname, channelName, fd);
|
||||
}
|
||||
else {
|
||||
if (channels[channelName].findUserFdForKickRegulars(nickname) == -1 && channelLimit == 1) {
|
||||
limitchannelforincrement = limitchannelforincrement + 1;
|
||||
}
|
||||
// Channel already exists, just add the user to it
|
||||
it->second.addClient(nickname, fd);
|
||||
// Send JOIN message to the client
|
||||
sendJoinMsg(nickname, channelName, fd);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::addUserToChannel(const std::string& nickname, const std::string& channelName, int fd) {
|
||||
Channel newChannel(channelName);
|
||||
newChannel.addClient(nickname, fd);
|
||||
newChannel.addOperator(nickname, fd);
|
||||
opperatorfd = fd;
|
||||
|
||||
std::string creationTimeMessage = constructCreationTimeMessage(channelName);
|
||||
std::string joinMessage = JOIN_MESSAGE(nickname, channelName);
|
||||
std::string modeMessage = MODE_MESSAGE(channelName);
|
||||
std::string namesMessage = NAMES_MESSAGE(nickname, channelName);
|
||||
std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName);
|
||||
std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage);
|
||||
|
||||
send(fd, joinMessage.c_str(), joinMessage.length(), 0);
|
||||
send(fd, modeMessage.c_str(), modeMessage.length(), 0);
|
||||
send(fd, namesMessage.c_str(), namesMessage.length(), 0);
|
||||
send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0);
|
||||
send(fd, channelMessage.c_str(), channelMessage.length(), 0);
|
||||
|
||||
channels.insert(std::make_pair(channelName, newChannel));
|
||||
}
|
BIN
Srcs/Channel.o
Normal file
BIN
Srcs/Channel.o
Normal file
Binary file not shown.
BIN
Srcs/Client.o
Normal file
BIN
Srcs/Client.o
Normal file
Binary file not shown.
263
Srcs/Commands.cpp
Normal file
263
Srcs/Commands.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
void Server::ping(const std::string& command, int fd) {
|
||||
std::istringstream iss(command);
|
||||
std::string serverHostname = command.substr(5);
|
||||
std::string pongMessage = "PONG " + serverHostname + "\r\n";
|
||||
send(fd, pongMessage.c_str(), pongMessage.length(), 0);
|
||||
std::cout << "PONG" << std::endl;
|
||||
}
|
||||
|
||||
void Server::processJoinCmd(Client& client, const std::string& command, int fd)
|
||||
{
|
||||
std::string nick;
|
||||
for (size_t i = 0; i < _clients.size(); ++i) {
|
||||
if (_clients[i].getFd() == fd) {
|
||||
nick = _clients[i].getNick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::string channelName, pass ;
|
||||
std::istringstream iss(command.substr(5));
|
||||
iss >> channelName ;
|
||||
if (channelName[0] != '#')
|
||||
{
|
||||
std::string what = " :Error: Channel start with #\r\n";
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
channelName = channelName.substr(1);
|
||||
channelName = trim(channelName);
|
||||
std::getline(iss, pass);
|
||||
pass = trim(pass);
|
||||
|
||||
// Check if the channel already exists
|
||||
std::map<std::string, Channel>::iterator it = channels.find(channelName);
|
||||
if (it != channels.end())
|
||||
{
|
||||
// Channel already exists
|
||||
std::string what = " :Error: CHANNEL limit\r\n";
|
||||
if ((isinvited == 1 && channels[channelName].isInvited(nick)) || channels[channelName].isOperator(fd))
|
||||
{
|
||||
// User is invited, create the channel
|
||||
int check = channels[channelName].getChannelLimit();
|
||||
if (limitchannelforincrement < check || channelLimit == 0)
|
||||
createChannel(channelName, nick, fd);
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
else if (isinvited == 0) {
|
||||
if (itHasPass == 1 && channels[channelName].getPass() == pass) {
|
||||
int check = channels[channelName].getChannelLimit();
|
||||
if (limitchannelforincrement < check || channelLimit == 0)
|
||||
createChannel(channelName, nick, fd);
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
else if (itHasPass == 0) {
|
||||
int check = channels[channelName].getChannelLimit();
|
||||
if (limitchannelforincrement < check || channelLimit == 0)
|
||||
createChannel(channelName, nick, fd);
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
else if (itHasPass == 1 && channels[channelName].getPass() != pass) {
|
||||
what = " :Error: you need a password for this channel\r\n";
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// User is not invited, send error message
|
||||
what = " :Error: you are not invited\r\n";
|
||||
std::string errorMessage = ERROR_MESSAGE2(nick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
createChannel(channelName, nick, fd);
|
||||
}
|
||||
|
||||
void Server::processPrivmsgCmd(Client& client, const std::string& command, int fd)
|
||||
{
|
||||
std::istringstream iss(command);
|
||||
std::string cmd, recipient, message;
|
||||
std::string niiick;
|
||||
|
||||
iss >> cmd >> recipient;
|
||||
recipient = trim(recipient);
|
||||
std::getline(iss, message);
|
||||
|
||||
if (iss.fail()) {
|
||||
std::string errorMessage = "Error: You Just missing an argument(5)\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
message = trim(message);
|
||||
message = message.substr(1);
|
||||
if (recipient[0] == '#') {
|
||||
recipient = recipient.substr(1);
|
||||
for (size_t i = 0; i < _clients.size(); ++i) {
|
||||
if (_clients[i].getFd() == fd) {
|
||||
niiick = _clients[i].getNick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
broadcastMessage(recipient, niiick, message);
|
||||
}
|
||||
else {
|
||||
handlePrivateMessage(fd, recipient, message);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processQuitCmd(int fd) {
|
||||
cleanChannel(fd);
|
||||
clientCleanup(fd);
|
||||
std::cout << "Client <" << fd << "> Disconnected" << std::endl;
|
||||
}
|
||||
|
||||
void Server::processKickCmd(Client& client, const std::string& command, int fd)
|
||||
{
|
||||
std::string channelName, userToKick, reason;
|
||||
std::istringstream iss(command.substr(5));
|
||||
iss >> channelName >> userToKick;
|
||||
|
||||
if (iss.fail()) {
|
||||
std::string errorMessage = "Error: You Just missing an argument(4)\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
std::getline(iss, reason);
|
||||
channelName = channelName.substr(1);
|
||||
channelName = trim(channelName);
|
||||
userToKick = trim(userToKick);
|
||||
reason = trim(reason);
|
||||
|
||||
std::string sender = channels[channelName].getNickname(fd);
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
int userFd = channels[channelName].findUserFdForKickRegulars(userToKick);
|
||||
if (userFd != -1) {
|
||||
channels[channelName].ejectUserfromusers(userFd);
|
||||
channels[channelName].ejectUserfromivited(userToKick);
|
||||
std::string kickMessage = KICK_MESSAGE2(channelName, fd, userToKick, reason);
|
||||
smallBroadcastMsgForKick(sender, channelName, userToKick, reason);
|
||||
send(fd, kickMessage.c_str(), kickMessage.length(), 0);
|
||||
send(userFd , kickMessage.c_str(), kickMessage.length(), 0);
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE3(sender, channelName, userToKick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE4(sender, channelName, userToKick);
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processTopicCmd(Client& client, const std::string& command, int fd)
|
||||
{
|
||||
std::string channelName, topic;
|
||||
std::istringstream iss(command.substr(6));
|
||||
iss >> channelName;
|
||||
std::getline(iss, topic);
|
||||
|
||||
if (iss.fail()) {
|
||||
std::string errorMessage = "Error: You Just missing an argument(3)\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
channelName = channelName.substr(1);
|
||||
channelName = trim(channelName);
|
||||
topic = trim(topic);
|
||||
topic = topic.substr(1);
|
||||
|
||||
std::string sender = channels[channelName].getNickname(fd);
|
||||
if ((channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) || issettop == 1) {
|
||||
channels[channelName].setTopic(topic);
|
||||
std::string topicMessage = TOPIC_MESSAGE2(sender, channelName, topic);
|
||||
send(fd, topicMessage.c_str(), topicMessage.size(), 0);
|
||||
smallbroadcastMessageforTopic(sender, channelName, topic);
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE6(sender, channelName);
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processInviteCmd(Client& client, const std::string& command, int fd) {
|
||||
std::string channelName, nickname;
|
||||
std::istringstream iss(command.substr(7));
|
||||
iss >> nickname >> channelName;
|
||||
|
||||
if (iss.fail()) {
|
||||
std::string errorMessage = "Error: You Just missing an argument(2)\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
channelName = trim(channelName);
|
||||
nickname = trim(nickname);
|
||||
channelName = channelName.substr(1);
|
||||
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
channels[channelName].addClientinveted(nickname, fd);
|
||||
handleInvitation(fd, nickname, channelName);
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE7(channelName, fd);
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::processBotCmd(Client& client, const std::string& command, int fd) {
|
||||
std::string start, end, guessed;
|
||||
std::istringstream iss(command.substr(4));
|
||||
iss >> start >> end >> guessed;
|
||||
std::string reme;
|
||||
|
||||
if (iss.fail() || iss >> reme)
|
||||
{
|
||||
std::string errorMessage = "Error: Command take 3 parameters\n";
|
||||
send(fd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
start = trim(start);
|
||||
end = trim(end);
|
||||
guessed = trim(guessed);
|
||||
|
||||
if (stringToInt(start) < stringToInt(end) && stringToInt(guessed) >= stringToInt(start) && stringToInt(guessed) <= stringToInt(end)) {
|
||||
int r = randomInRange(stringToInt(start), stringToInt(end));
|
||||
std::string random = intToString(r);
|
||||
if (random == guessed) {
|
||||
std::string congratsMsg = CONGRATS_MSG(guessed);
|
||||
send(fd, congratsMsg.c_str(), congratsMsg.size(), 0);
|
||||
}
|
||||
else {
|
||||
std::string guessAgain = GUESS_AGAIN(random);
|
||||
send(fd, guessAgain.c_str(), guessAgain.size(), 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = GUESS_ERROR();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
BIN
Srcs/Commands.o
Normal file
BIN
Srcs/Commands.o
Normal file
Binary file not shown.
193
Srcs/Helpers.cpp
Normal file
193
Srcs/Helpers.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
void Server::parseArgs(int ac, char **av) {
|
||||
if (ac != 3)
|
||||
throw std::runtime_error("Usage: ./ircserv <port> <password>");
|
||||
std::string port(av[1]);
|
||||
std::string pwd(av[2]);
|
||||
if (port.empty() || port.find_first_not_of("0123456789") != std::string::npos)
|
||||
throw std::runtime_error("Error: Invalid arguments");
|
||||
|
||||
long _port = atol(av[1]);
|
||||
if (!(_port >= 0 && _port <= 65535))
|
||||
throw std::runtime_error("Error: Invalid arguments");
|
||||
|
||||
if (pwd.empty())
|
||||
throw std::runtime_error("Error: Invalid arguments");
|
||||
|
||||
this->_port = _port;
|
||||
this->_password = pwd;
|
||||
}
|
||||
|
||||
std::string Server::intToString(int number) {
|
||||
std::stringstream ss;
|
||||
ss << number;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Server::trim(const std::string& str) {
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
if (std::string::npos == first) {
|
||||
return "";
|
||||
}
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
return str.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
bool Server::startsWith(const std::string& str, const std::string& prefix) {
|
||||
return str.substr(0, prefix.length()) == prefix;
|
||||
}
|
||||
|
||||
int Server::stringToInt(const std::string& str) {
|
||||
std::stringstream ss(str);
|
||||
int result;
|
||||
ss >> result;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Server::isValidPassword(const std::string& passwordLine) {
|
||||
if (!passwordLine.empty() &&
|
||||
((passwordLine[0] == '"' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '"') ||
|
||||
(passwordLine[0] == '\'' && passwordLine.size() > 1 && passwordLine[passwordLine.size() - 1] == '\''))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string Server::formatCreationTime() {
|
||||
std::time_t currentTime = std::time(NULL);
|
||||
std::tm* localTime = std::localtime(¤tTime);
|
||||
|
||||
char buffer[80];
|
||||
std::strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", localTime);
|
||||
return std::string(buffer);
|
||||
}
|
||||
|
||||
std::string Server::constructCreationTimeMessage(const std::string& channelName) {
|
||||
std::stringstream ss;
|
||||
ss << "Channel #" << channelName << " created " << formatCreationTime();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string Server::constructJoinedTimeMessage(const std::string& channelName) {
|
||||
std::stringstream ss;
|
||||
ss << "Channel #" << channelName << " Joined " << formatCreationTime();
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void Server::closeFds()
|
||||
{
|
||||
for (size_t i = 0; i < _clients.size(); i++){
|
||||
int fd = _clients[i].getFd();
|
||||
std::cout << "Client <" << fd << "> Disconnected" << std::endl;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (_serverSocketFd != -1)
|
||||
close(_serverSocketFd);
|
||||
_fds.clear();
|
||||
}
|
||||
|
||||
void Server::cleanChannel(int fd) {
|
||||
std::map<std::string, Channel>::iterator it;
|
||||
for (it = channels.begin(); it != channels.end(); ++it)
|
||||
{
|
||||
Channel& channel = it->second;
|
||||
std::string nickname = channel.getNickname(fd);
|
||||
if (channel.isUserInChannel(nickname)) {
|
||||
channel.ejectUserfromusers(fd);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<int, std::string>::iterator userIt;
|
||||
userIt = usernames.find(fd);
|
||||
if (userIt != usernames.end()) {
|
||||
usernames.erase(userIt);
|
||||
}
|
||||
|
||||
std::map<int, std::string>::iterator nickIt;
|
||||
nickIt = nicknames.find(fd);
|
||||
if (nickIt != nicknames.end()) {
|
||||
nicknames.erase(nickIt);
|
||||
}
|
||||
|
||||
for (std::map<std::string, Channel>::iterator it = channels.begin(); it != channels.end(); ++it) {
|
||||
std::map<std::string, int> &usersfdmap = it->second.getUserFdMap();
|
||||
for (std::map<std::string, int>::iterator it2 = usersfdmap.begin(); it2 != usersfdmap.end(); ++it2) {
|
||||
if (it2->second == fd)
|
||||
usersfdmap.erase(it2);
|
||||
}
|
||||
}
|
||||
for (std::map<std::string, Channel>::iterator it1 = channels.begin(); it1 != channels.end(); ++it1) {
|
||||
std::map<std::string, int> &invitedusrmap = it1->second.invitedUserss();
|
||||
for (std::map<std::string, int>::iterator it2 = invitedusrmap.begin(); it2 != invitedusrmap.end(); ++it2) {
|
||||
if (it2->second == fd)
|
||||
invitedusrmap.erase(it2);
|
||||
}
|
||||
}
|
||||
for (std::map<std::string, Channel>::iterator it2 = channels.begin(); it2 != channels.end(); ++it2) {
|
||||
std::map<std::string, int> &operatorsmap = it2->second.getOperators();
|
||||
for (std::map<std::string, int>::iterator it2 = operatorsmap.begin(); it2 != operatorsmap.end(); ++it2) {
|
||||
if (it2->second == fd)
|
||||
operatorsmap.erase(it2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::clientCleanup(int fd) {
|
||||
for (std::vector<pollfd>::iterator it = _fds.begin(); it != _fds.end(); ++it) {
|
||||
if (it->fd == fd) {
|
||||
_fds.erase(it);
|
||||
close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::vector<Client>::iterator it = _clients.begin(); it != _clients.end(); ++it) {
|
||||
if (it->getFd() == fd) {
|
||||
_clients.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Server::randomInRange(int min, int max)
|
||||
{
|
||||
if (min > max) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int range_size = max - min + 1;
|
||||
double random_double = (double)rand() / (RAND_MAX + 1.0) * range_size;
|
||||
|
||||
return (int)random_double + min;
|
||||
}
|
||||
|
||||
// find nicknames of the users to brodcast to
|
||||
int Server::findUserFd1(const std::string& username) {
|
||||
std::map<int, std::string>::iterator it;
|
||||
for (it = nicknames.begin(); it != nicknames.end(); ++it) {
|
||||
if (it->second == username)
|
||||
return it->first;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Server::dontputthesamenick(const std::string& nickname) {
|
||||
std::map<int, std::string>::iterator it;
|
||||
for (it = nicknames.begin(); it != nicknames.end(); ++it) {
|
||||
if (it->second == nickname)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Server::dontputthesameusername(const std::string& username) {
|
||||
std::map<int, std::string>::iterator it;
|
||||
for (it = usernames.begin(); it != usernames.end(); ++it) {
|
||||
if (it->second == username) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
BIN
Srcs/Helpers.o
Normal file
BIN
Srcs/Helpers.o
Normal file
Binary file not shown.
170
Srcs/Modes.cpp
Normal file
170
Srcs/Modes.cpp
Normal file
@@ -0,0 +1,170 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
void Server::processModeCmd(Client& client, const std::string& command, int fd) {
|
||||
std::string channelName, mode , nick;
|
||||
std::istringstream iss(command.substr(5));
|
||||
iss >> channelName >> mode >> nick;
|
||||
|
||||
if (channelName[0] != '#') {
|
||||
client.clearCommand();
|
||||
return;
|
||||
}
|
||||
|
||||
channelName = channelName.substr(1);
|
||||
channelName = trim(channelName);
|
||||
mode = trim(mode);
|
||||
size_t opt = mode.length() - 1;
|
||||
|
||||
if (mode[opt] == 'o')
|
||||
handleOpPrivilege(nick, channelName, mode, fd);
|
||||
else if (mode[opt] == 't')
|
||||
handleTopicRestriction(nick, channelName, mode, fd);
|
||||
else if (mode[opt] == 'i')
|
||||
handleInviteOnly(nick, channelName, mode, fd);
|
||||
else if (mode[opt] == 'k')
|
||||
handleChannelKey(nick, channelName, mode, fd);
|
||||
else if (mode[opt] == 'l')
|
||||
handleChannelLimit(nick, channelName, mode, fd);
|
||||
}
|
||||
|
||||
void Server::handleOpPrivilege(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) {
|
||||
if (mode == "+o") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
channels[channelName].addOperator(nick, channels[channelName].getUserFd(nick));
|
||||
abaaba = channels[channelName].getUserFd(nick);
|
||||
std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE7(channelName, fd);
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == "-o") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
channels[channelName].removeOperator(nick);
|
||||
std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleTopicRestriction(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) {
|
||||
if (mode == "-t") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = TOPIC_CHANGE_MESSAGE(channelName, mode, fd);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
issettop = 1;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == "+t") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = TOPIC_CHANGE_MESSAGE(channelName, mode, fd);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
issettop = 0;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleInviteOnly(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) {
|
||||
if (mode == "+i") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
isinvited = 1;
|
||||
}
|
||||
else if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd) == false) {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
|
||||
}
|
||||
else if (mode == "-i") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick);;
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
isinvited = 0;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleChannelKey(std::string& nick, const std::string& channelName, const std::string& mode, int fd) {
|
||||
if (mode == "-k") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
itHasPass = 0;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == "+k") {
|
||||
nick = trim(nick);
|
||||
channels[channelName].setPass(nick);
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
itHasPass = 1;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleChannelLimit(const std::string& nick, const std::string& channelName, const std::string& mode, int fd) {
|
||||
if (mode == "+l") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
int limit = stringToInt(nick);
|
||||
channels[channelName].setlimitchannel(limit);
|
||||
std::string modeChangeMessage = MODE_SET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
channelLimit = 1;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
else if (mode == "-l") {
|
||||
if (channels.find(channelName) != channels.end() && channels[channelName].isOperator(fd)) {
|
||||
std::string modeChangeMessage = MODE_UNSET_MESSAGE(channelName, mode, fd, nick);
|
||||
send(fd, modeChangeMessage.c_str(), modeChangeMessage.size(), 0);
|
||||
smallbroadcastMOOD(channels[channelName].getNickname(fd), channelName, mode, nick);
|
||||
channelLimit = 0;
|
||||
limitchannelforincrement = 0;
|
||||
}
|
||||
else {
|
||||
std::string errorMessage = ERROR_MESSAGE5();
|
||||
send(fd, errorMessage.c_str(), errorMessage.size(), 0);
|
||||
}
|
||||
}
|
||||
}
|
BIN
Srcs/Modes.o
Normal file
BIN
Srcs/Modes.o
Normal file
Binary file not shown.
239
Srcs/Server.cpp
Normal file
239
Srcs/Server.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
#include "Server.hpp"
|
||||
|
||||
int opperatorfd = 0;
|
||||
int issettop = 0;
|
||||
int isinvited = 0;
|
||||
int itHasPass = 0;
|
||||
int channelLimit = 0;
|
||||
int limitchannelforincrement = 0;
|
||||
int abaaba = 0;
|
||||
|
||||
bool Server::_signal = false;
|
||||
|
||||
Server::Server() {}
|
||||
|
||||
Server::~Server() {}
|
||||
|
||||
std::string Server::getPassowrd() const {
|
||||
return _password;
|
||||
}
|
||||
|
||||
void Server::receiveSignal(int signum) {
|
||||
_signal = true;
|
||||
(void)signum;
|
||||
}
|
||||
|
||||
Client& Server::getClientByFd(int fd) {
|
||||
size_t i = 0;
|
||||
for (; i < _clients.size(); ++i) {
|
||||
if (_clients[i].getFd() == fd)
|
||||
break;
|
||||
}
|
||||
return _clients[i];
|
||||
}
|
||||
|
||||
void Server::setNickname(int fd, const std::string& nickname) {nicknames[fd] = nickname;}
|
||||
|
||||
void Server::setUsernames(int fd, const std::string& username) {usernames[fd] = username;}
|
||||
|
||||
void Server::init() {
|
||||
signal(SIGINT, receiveSignal);
|
||||
signal(SIGQUIT, receiveSignal);
|
||||
|
||||
createServerSocket();
|
||||
std::cout << GREEN << ">>> SERVER STARTED <<<" << RESET << std::endl;
|
||||
std::cout << CYAN <<"Waiting for connections..." << RESET << std::endl;
|
||||
}
|
||||
|
||||
void Server::run() {
|
||||
while (!_signal) {
|
||||
int ret = poll(&_fds[0], _fds.size(), -1);
|
||||
if (ret == -1 && !_signal)
|
||||
throw std::runtime_error("Error: poll() failed");
|
||||
|
||||
for (size_t i = 0; i < _fds.size(); ++i) {
|
||||
if (_fds[i].revents & POLLIN) {
|
||||
if (_fds[i].fd == _serverSocketFd)
|
||||
handleClientConnection();
|
||||
else
|
||||
handleClientData(_fds[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
closeFds();
|
||||
}
|
||||
|
||||
void Server::createServerSocket() {
|
||||
_serverSocketFd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (_serverSocketFd == -1)
|
||||
throw std::runtime_error("Error: failed to create socket");
|
||||
|
||||
int optval = 1;
|
||||
if (setsockopt(_serverSocketFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1)
|
||||
throw std::runtime_error("Error: setsockopt() failed");
|
||||
|
||||
if (fcntl(_serverSocketFd, F_SETFL, O_NONBLOCK) == -1)
|
||||
throw std::runtime_error("Error: fcntl() failed");
|
||||
|
||||
bindServerSocket();
|
||||
|
||||
if (listen(_serverSocketFd, SOMAXCONN) == -1)
|
||||
throw std::runtime_error("Error: listen() failed");
|
||||
|
||||
addPollfd(_serverSocketFd);
|
||||
}
|
||||
|
||||
void Server::bindServerSocket() {
|
||||
struct sockaddr_in sa;
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = htons(_port);
|
||||
sa.sin_addr.s_addr = INADDR_ANY;
|
||||
if (bind(_serverSocketFd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
||||
throw std::runtime_error("Error: failed to bind socket");
|
||||
}
|
||||
}
|
||||
|
||||
void Server::addPollfd(int fd) {
|
||||
struct pollfd newPollfd;
|
||||
newPollfd.fd = fd;
|
||||
newPollfd.events = POLLIN;
|
||||
newPollfd.revents = 0;
|
||||
_fds.push_back(newPollfd);
|
||||
}
|
||||
|
||||
void Server::handleClientConnection() {
|
||||
struct sockaddr_in client_addr;
|
||||
socklen_t clientAddrSize = sizeof(sockaddr_in);
|
||||
int newFd = accept(_serverSocketFd, (struct sockaddr *)&client_addr, &clientAddrSize);
|
||||
if (newFd == -1)
|
||||
throw std::runtime_error("Error: accept() failed");
|
||||
|
||||
if (fcntl(newFd, F_SETFL, O_NONBLOCK) == -1)
|
||||
throw std::runtime_error("Error: fcntl() failed");
|
||||
|
||||
std::string passwordRequest = "Please Enter The password Of This Server :\n";
|
||||
std::string art = MINICHAT;
|
||||
|
||||
send(newFd, art.c_str(), art.length(), 0);
|
||||
send(newFd, passwordRequest.c_str(), passwordRequest.length(), 0);
|
||||
addPollfd(newFd);
|
||||
_clients.push_back(Client(newFd));
|
||||
|
||||
std::cout << "Client <" << newFd << "> Connected" << std::endl;
|
||||
}
|
||||
|
||||
void Server::sendJoinMsg(const std::string& nickname, const std::string& channelName, int fd) {
|
||||
std::string operators = channels[channelName].getOperatorNickname(opperatorfd);
|
||||
std::string operators1 = channels[channelName].getOperatorNickname(abaaba);
|
||||
|
||||
std::string topic = channels[channelName].getTopic();
|
||||
std::string creationTimeMessage = constructJoinedTimeMessage(channelName);
|
||||
std::string joinMessage = JOIN_MESSAGE(nickname, channelName);
|
||||
std::string topicMessage = TOPIC_MESSAGE(nickname, channelName, topic);
|
||||
|
||||
send(fd, joinMessage.c_str(), joinMessage.length(), 0);
|
||||
send(fd, topicMessage.c_str(), topicMessage.length(), 0);
|
||||
|
||||
std::string namesMessage = NAMES_MESSAGE2(nickname, channelName);
|
||||
const std::vector<std::string>& clients = channels[channelName].getClients();
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
const std::string& user = clients[i];
|
||||
if (user == operators || user == operators1) {
|
||||
namesMessage += "@" + user;
|
||||
} else {
|
||||
namesMessage += user;
|
||||
}
|
||||
if (i < clients.size() - 1)
|
||||
namesMessage += " ";
|
||||
}
|
||||
namesMessage += "\n";
|
||||
std::string endOfNamesMessage = END_OF_NAMES_MESSAGE(nickname, channelName);
|
||||
std::string channelMessage = CHANNEL_MESSAGE(channelName, creationTimeMessage);
|
||||
|
||||
send(fd, namesMessage.c_str(), namesMessage.length(), 0);
|
||||
send(fd, endOfNamesMessage.c_str(), endOfNamesMessage.length(), 0);
|
||||
send(fd, channelMessage.c_str(), channelMessage.length(), 0);
|
||||
|
||||
smallbroadcastMessageforjoin(nickname, channelName);
|
||||
}
|
||||
|
||||
// handling private msg between users only
|
||||
void Server::handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message) {
|
||||
int recipientFd = findUserFd1(recipient);
|
||||
if (recipientFd != -1) {
|
||||
std::string privateMessage = PRIVATE_MESSAGE(senderFd, recipient, message);
|
||||
send(recipientFd, privateMessage.c_str(), privateMessage.length(), 0);
|
||||
} else {
|
||||
std::string errorMessage = ERROR_MESSAGE(senderFd, recipient);
|
||||
send(senderFd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleInvitation(int senderFd, const std::string& recipient, std::string channelName) {
|
||||
int recipientFd = findUserFd1(recipient);
|
||||
|
||||
if (recipientFd != -1) {
|
||||
std::string inviteMessage = INVITE_MESSAGE(senderFd, recipient, channelName);
|
||||
send(recipientFd, inviteMessage.c_str(), inviteMessage.length(), 0);
|
||||
} else {
|
||||
std::string errorMessage = ERROR_MESSAGE(senderFd, recipient);
|
||||
send(senderFd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleClientData(int fd)
|
||||
{
|
||||
Client& client = getClientByFd(fd);
|
||||
char buffer[BUFFER_SIZE];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
ssize_t bytesRead = recv(fd, buffer, BUFFER_SIZE - 1, 0);
|
||||
if (bytesRead > 0) {
|
||||
buffer[bytesRead] = '\0';
|
||||
client.appendCommand(buffer);
|
||||
size_t newlinePos = client.getCommand().find_first_of("\r\n");
|
||||
if (newlinePos != std::string::npos) {
|
||||
std::string command = client.getCommand().substr(0, newlinePos);
|
||||
client.setCommand(command);
|
||||
std::cout << "Received data from client " << fd << ": " << command << std::endl;
|
||||
int auth = client.getAuthentication();
|
||||
|
||||
if ((startsWith(command, "PASS ") || startsWith(command, "pass ")) && auth == 0)
|
||||
processPassword(client, command, fd);
|
||||
else if ((startsWith(command, "NICK ") || startsWith(command, "nick ")) && auth == 1)
|
||||
processNickCmd(client, command, fd);
|
||||
else if ((startsWith(command, "USER ") || startsWith(command, "user ")) && auth == 2)
|
||||
processUserCmd(client, command, fd);
|
||||
else if (startsWith(command, "JOIN ") || startsWith(command, "join "))
|
||||
processJoinCmd(client, command, fd);
|
||||
else if (startsWith(command, "PRIVMSG ") || startsWith(command, "privmsg "))
|
||||
processPrivmsgCmd(client, command, fd);
|
||||
else if (startsWith(command, "KICK ") || startsWith(command, "kick "))
|
||||
processKickCmd(client, command, fd);
|
||||
else if (startsWith(command, "TOPIC ") || startsWith(command, "topic "))
|
||||
processTopicCmd(client, command, fd);
|
||||
else if (startsWith(command, "INVITE ") || startsWith(command, "invite "))
|
||||
processInviteCmd(client, command, fd);
|
||||
else if (startsWith(command, "BOT ") || startsWith(command, "bot "))
|
||||
processBotCmd(client, command, fd);
|
||||
else if (startsWith(command, "MODE ") || startsWith(command, "mode "))
|
||||
processModeCmd(client, command, fd);
|
||||
else if (startsWith(command, "QUIT") || startsWith(command, "quit"))
|
||||
processQuitCmd(fd);
|
||||
else if (startsWith(command, "PING"))
|
||||
ping(command, fd);
|
||||
|
||||
client.clearCommand();
|
||||
}
|
||||
}
|
||||
|
||||
else if (bytesRead == 0) {
|
||||
std::cout << "Client <" << fd << "> Disconnected" << std::endl;
|
||||
cleanChannel(fd);
|
||||
clientCleanup(fd);
|
||||
} else if (bytesRead == -1) {
|
||||
std::cerr << "Error reading data from client <" << fd << ">" << std::endl;
|
||||
cleanChannel(fd);
|
||||
clientCleanup(fd);
|
||||
}
|
||||
}
|
BIN
Srcs/Server.o
Normal file
BIN
Srcs/Server.o
Normal file
Binary file not shown.
Reference in New Issue
Block a user