Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ bool Channel::kick(int op, int user) {

bool Channel::message(int user, string msg, string type, string name) {
string message;
bool ret = true;

if (type.empty())
message = msg + "\r\n";
Expand All @@ -241,14 +242,14 @@ bool Channel::message(int user, string msg, string type, string name) {
for (auto users : _users) {
if (users == user)
continue;
else if (-1 == send(users, message.data(), message.size(), 0))
return false;
if (-1 == send(users, message.data(), message.size(), 0))
ret = false;
}
for (auto users : _oper) {
if (users == user)
continue;
if (-1 == send(users, message.data(), message.size(), 0))
return false;
ret = false;
}
return true;
return ret;
}
264 changes: 131 additions & 133 deletions src/Server.cpp
Original file line number Diff line number Diff line change
@@ -1,171 +1,169 @@
#include "Server.hpp"

Server::Server(std::string port, std::string passwd) :
_startTime(time(nullptr)),
_fd(epoll_create1(0)),
_sock(socket(AF_INET, SOCK_STREAM, 0)),
_checker(0),
_port(stoi(port, &_checker)),
_password(passwd)
{
if(_fd == -1)
throw std::runtime_error("Server::Server: ERROR - Failed to create epoll file");
else if (port[_checker])
throw std::runtime_error("Server::Server: ERROR - Bad port number " + port);
auto optval = 1;
setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
struct sockaddr_in sa_bindy{};
sa_bindy.sin_family = AF_INET;
sa_bindy.sin_port = htons(_port);
sa_bindy.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(_sock, (struct sockaddr *)&sa_bindy, sizeof(sa_bindy))) {
close(_fd);
close(_sock);
throw std::runtime_error("Server::Server: ERROR - Binding failed to " + port);
}

if (listen(_sock, 10)) {
close(_fd);
close(_sock);
throw std::runtime_error("Server::Server: ERROR - Failed listen on port " + port);
}

struct epoll_event ev{};
ev.data.fd = _sock;
ev.events = EPOLLIN;
epoll_ctl(this->_fd, EPOLL_CTL_ADD, _sock, &ev);

_events.reserve(_max_events * sizeof(epoll_event));
Server::Server(std::string port, std::string passwd)
: _startTime(time(nullptr)), _fd(epoll_create1(0)),
_sock(socket(AF_INET, SOCK_STREAM, 0)), _checker(0),
_port(stoi(port, &_checker)), _password(passwd) {
if (_fd == -1)
throw std::runtime_error(
"Server::Server: ERROR - Failed to create epoll file");
else if (port[_checker])
throw std::runtime_error("Server::Server: ERROR - Bad port number " + port);
auto optval = 1;
setsockopt(_sock, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
struct sockaddr_in sa_bindy{};
sa_bindy.sin_family = AF_INET;
sa_bindy.sin_port = htons(_port);
sa_bindy.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(_sock, (struct sockaddr *)&sa_bindy, sizeof(sa_bindy))) {
close(_fd);
close(_sock);
throw std::runtime_error("Server::Server: ERROR - Binding failed to " +
port);
}

if (listen(_sock, 10)) {
close(_fd);
close(_sock);
throw std::runtime_error("Server::Server: ERROR - Failed listen on port " +
port);
}

struct epoll_event ev{};
ev.data.fd = _sock;
ev.events = EPOLLIN;
epoll_ctl(this->_fd, EPOLL_CTL_ADD, _sock, &ev);
_events.resize(_max_events);
}

Server::~Server() {
close(_fd);
close(_sock);
close(_fd);
close(_sock);
}

bool Server::checkPassword(std::string password) const {
return _password == password;
return _password == password;
}

int Server::getServerFd() const {
return _fd;
}
int Server::getServerFd() const { return _fd; }

Channel& Server::addChannel(std::string name) {
_channels.try_emplace(name, name);
return _channels.at(name);
Channel &Server::addChannel(std::string name) {
_channels.try_emplace(name, name);
return _channels.at(name);
}

void Server::removeChannel(std::string name) {
_channels.erase(name);
}
void Server::removeChannel(std::string name) { _channels.erase(name); }

bool Server::channelExists(std::string name) {
return _channels.contains(name);
return _channels.contains(name);
}

Channel* Server::findChannel(std::string name) {
auto ret = _channels.find(name);
if (ret == _channels.end())
return nullptr;
return &(ret->second);
Channel *Server::findChannel(std::string name) {
auto ret = _channels.find(name);
if (ret == _channels.end())
return nullptr;
return &(ret->second);
}

void Server::addClient(int fd) {
_clients.try_emplace(fd, std::make_shared<Client>(fd));
_clients.try_emplace(fd, std::make_shared<Client>(fd));
}

void Server::removeClient(const int fd) {
if(not _clients.empty()) {
_clients.erase(fd);
}
close(fd);
if (not _clients.empty()) {
_clients.erase(fd);
}
close(fd);
}

void Server::_reloadHandler(Client &client) const {
uint32_t event = 0;
struct epoll_event ev{};
ev.data.fd = client._fd;
bool firstEvent = true;

for (uint32_t evt: eventTypes) {
if (client.handler(evt)) {
event = evt;
firstEvent = false;
} else {
event |= evt;
}

if (firstEvent)
event = EPOLLET;
else
event |= EPOLLET;

ev.events = event;

if (client._initialized) {
epoll_ctl(this->_fd, EPOLL_CTL_MOD, client._fd, &ev);
} else {
epoll_ctl(this->_fd, EPOLL_CTL_ADD, client._fd, &ev);
client._initialized = true;
}
}
uint32_t event = 0;
struct epoll_event ev{};
ev.data.fd = client._fd;
bool firstEvent = true;

for (uint32_t evt : eventTypes) {
if (client.handler(evt)) {
event = evt;
firstEvent = false;
} else {
event |= evt;
}

if (firstEvent)
event = EPOLLET;
else
event |= EPOLLET;

ev.events = event;

if (client._initialized) {
epoll_ctl(this->_fd, EPOLL_CTL_MOD, client._fd, &ev);
} else {
epoll_ctl(this->_fd, EPOLL_CTL_ADD, client._fd, &ev);
client._initialized = true;
}
}
}

void Server::poll(int tout) {
int nbrEvents = epoll_wait(_fd, &_events[0], _max_events, tout);

for (int idx = 0; idx < nbrEvents; idx++) {
uint32_t event = _events[idx].events;
int fd = _events[idx].data.fd;
if (fd == _sock) {
Handler::acceptClient(_sock);
continue;
}
for (uint32_t type : eventTypes) {
if (_clients.count(fd) == 0)
return ;
if (_clients.at(fd)->handler(type & event)) {
[[maybe_unused]]
auto fut = std::async(std::launch::async, _clients.at(fd)->getHandler(type & event), fd);
}
}

if (event & (EPOLLRDHUP & EPOLLHUP))
removeClient(fd);
}
}

void Server::registerHandler(const int fd, uint32_t eventType, std::function<void(int)> handler) {
if (_clients.count(fd) == 0)
throw std::runtime_error("Server::registerHandler: Error - no such file descriptor");


Client *cli = _clients.at(fd).get();

for (uint32_t eventT: eventTypes) {
if (eventT & eventType) {
cli->setHandler(eventType, handler);
}
}

_reloadHandler(*cli);
int nbrEvents = epoll_wait(_fd, &_events[0], _max_events, tout);

for (int idx = 0; idx < nbrEvents; idx++) {
uint32_t event = _events[idx].events;
int fd = _events[idx].data.fd;
if (fd == _sock) {
Handler::acceptClient(_sock);
continue;
}
for (uint32_t type : eventTypes) {
if (_clients.count(fd) == 0)
return;
if (_clients.at(fd)->handler(type & event)) {
[[maybe_unused]]
auto fut = std::async(std::launch::async,
_clients.at(fd)->getHandler(type & event), fd);
}
}

if (event & (EPOLLRDHUP & EPOLLHUP))
removeClient(fd);
}
}

void Server::registerHandler(const int fd, uint32_t eventType,
std::function<void(int)> handler) {
if (_clients.count(fd) == 0)
throw std::runtime_error(
"Server::registerHandler: Error - no such file descriptor");

Client *cli = _clients.at(fd).get();

for (uint32_t eventT : eventTypes) {
if (eventT & eventType) {
cli->setHandler(eventType, handler);
}
}

_reloadHandler(*cli);
}

std::string Server::getTime(void) const {
string ret = ctime(&_startTime);
ret.pop_back();
return ret;
string ret = ctime(&_startTime);
ret.pop_back();
return ret;
}

const std::unordered_map<int, std::shared_ptr<Client>>& Server::getClients() const {
return (_clients);
const std::unordered_map<int, std::shared_ptr<Client>> &
Server::getClients() const {
return (_clients);
}

Client* Server::getClient(int fd) {
if (_clients.count(fd) == 0)
throw std::runtime_error("Server::getClient: Error - no such file descriptor");
Client *Server::getClient(int fd) {
if (_clients.count(fd) == 0)
throw std::runtime_error(
"Server::getClient: Error - no such file descriptor");

return (_clients.at(fd).get());
return (_clients.at(fd).get());
}
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int main(int argc, char *argv[]) {

signal(SIGINT, [](int) { gSigStatus = 1; });
signal(SIGQUIT, [](int) { gSigStatus = 1; });
signal(SIGPIPE, SIG_IGN);

try {
if (argc == 3)
Expand Down