changed project structure
This commit is contained in:
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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user