diff --git a/Makefile b/Makefile index 23cad93..4af14cf 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# **************************************************************************** # +#******************************************************************************# # # # ::: :::::::: # # Makefile :+: :+: :+: # @@ -6,9 +6,9 @@ # By: omoudni +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/02 15:40:00 by rparodi #+# #+# # -# Updated: 2025/05/19 15:13:05 by omoudni ### ########.fr # +# Updated: 2025/05/19 20:14:35 by omoudni ### ########.fr # # # -# **************************************************************************** # +#******************************************************************************# # Name @@ -28,6 +28,7 @@ SRC = sources/core/main.cpp \ sources/core/server.cpp \ sources/core/check.cpp \ sources/core/parser.cpp \ + sources/core/pollManager.cpp \ INC_DIR = include/core \ diff --git a/diagram.puml b/diagram.puml index 4621615..dc05a30 100644 --- a/diagram.puml +++ b/diagram.puml @@ -1,13 +1,16 @@ @startuml + ' ======================== ' CLASS: Server ' ======================== class Server { - _port : int - _password : string - - _clients : List + - _users : List - _server_fd : int + - _state_msg : std::pair + - _pollManager : PollManager + showInfo() : void + getPort() : int @@ -15,9 +18,9 @@ class Server { } ' ======================== -' CLASS: Client +' CLASS: User ' ======================== -class Client { +class User { - _id : int - _name : string - _registered : bool @@ -29,7 +32,7 @@ class Client { + isRegistered() : bool + joinChannel(channel : Channel) : void + leaveChannel(channel : Channel) : void - + sendMessage(to : Client, message : string) : void + + sendMessage(to : User, message : string) : void } ' ======================== @@ -38,23 +41,23 @@ class Client { class Channel { - _name : string - _password : string - - _owner : Client - - _operators : List + - _owner : User + - _operators : List - _socket_id : int - _topic : string + getName() : string + setTopic(newTopic : string) : void - + addOperator(client : Client) : void - + removeOperator(client : Client) : void + + addOperator(User : User) : void + + removeOperator(User : User) : void } ' ======================== ' CLASS: Commandes ' ======================== class Commandes { - - _form_user : Client - - _to_user : Client + - _form_user : User + - _to_user : User - _channel : Channel + MODE() : void @@ -85,14 +88,29 @@ class Parser { + getErrorMsg() : string } +' ======================== +' CLASS: PollManager +' ======================== +class PollManager { + - _fds : vector + - _fd_events : map + + + addFd(fd : int, events : short) : void + + removeFd(fd : int) : void + + updateFd(fd : int, events : short) : void + + pollEvents(timeout : int) : int + + getFds() : vector +} + ' ======================== ' RELATIONS ' ======================== -Server "1" o-- "*" Client : _clients -Client "1" o-- "*" Channel : _channels -Channel "1" *-- "1" Client : _owner -Channel "1" o-- "*" Client : _operators +Server "1" o-- "*" User : _users +User "1" o-- "*" Channel : _channels +Channel "1" *-- "1" User : _owner +Channel "1" o-- "*" User : _operators main ..> Parser : uses +Server "1" *-- "1" PollManager : pollManager @enduml \ No newline at end of file diff --git a/include/core/core.hpp b/include/core/core.hpp index 74d6c2b..3691a10 100644 --- a/include/core/core.hpp +++ b/include/core/core.hpp @@ -1,4 +1,4 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* core.hpp :+: :+: :+: */ @@ -6,9 +6,9 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/12 14:16:03 by rparodi #+# #+# */ -/* Updated: 2025/05/19 15:07:26 by omoudni ### ########.fr */ +/* Updated: 2025/05/19 20:15:14 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once @@ -16,11 +16,21 @@ #define LOG std::endl << CLR_CYAN << "Debug: " << __FILE__ << ":" << __LINE__ << std::endl << CLR_RESET #endif + + #ifndef DEBUG #define DEBUG 0 #define LOG "" #endif +enum e_state { + ERROR = 0, + CMD, + MSG + }; + + +#include "pollManager.hpp" #include "color.hpp" #include "server.hpp" #include "parser.hpp" diff --git a/include/core/pollManager.hpp b/include/core/pollManager.hpp new file mode 100644 index 0000000..d7a0770 --- /dev/null +++ b/include/core/pollManager.hpp @@ -0,0 +1,30 @@ +/******************************************************************************/ +/* */ +/* ::: :::::::: */ +/* pollManager.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: omoudni +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/19 19:15:13 by omoudni #+# #+# */ +/* Updated: 2025/05/19 19:25:45 by omoudni ### ########.fr */ +/* */ +/******************************************************************************/ + +#pragma once +#include +#include +#include + +class PollManager { +private: + std::vector _fds; + std::map _fd_events; // fd -> event + +public: + PollManager(); + void addFd(int fd, short events); + void removeFd(int fd); + void updateFd(int fd, short events); + int pollEvents(int timeout = -1); + const std::vector& getFds() const; +}; \ No newline at end of file diff --git a/include/core/server.hpp b/include/core/server.hpp index e29640d..da0c8ce 100644 --- a/include/core/server.hpp +++ b/include/core/server.hpp @@ -1,17 +1,18 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* server.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: omoudni +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:06:56 by rparodi #+# #+# */ -/* Updated: 2025/05/14 23:23:13 by omoudni ### ########.fr */ +/* Updated: 2025/05/19 20:12:46 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once +#include "core.hpp" #include class Server { @@ -19,6 +20,7 @@ class Server { unsigned short int _port; std::string _password; int server_fd; + PollManager _pollManager; public: Server(); Server(int port, const std::string &password); diff --git a/sources/core/pollManager.cpp b/sources/core/pollManager.cpp new file mode 100644 index 0000000..a02bff2 --- /dev/null +++ b/sources/core/pollManager.cpp @@ -0,0 +1,50 @@ +/******************************************************************************/ +/* */ +/* ::: :::::::: */ +/* pollManager.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: omoudni +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/19 19:15:48 by omoudni #+# #+# */ +/* Updated: 2025/05/19 20:21:11 by omoudni ### ########.fr */ +/* */ +/******************************************************************************/ + +#include "pollManager.hpp" +#include + +PollManager::PollManager() {} + +void PollManager::addFd(int fd, short events) { + struct pollfd pfd = {fd, events, 0}; + _fds.push_back(pfd); + _fd_events[fd] = events; +} + +void PollManager::removeFd(int fd) { + for (std::vector::iterator it = _fds.begin(); it != _fds.end(); ) { + if (it->fd == fd) + it = _fds.erase(it); + else + ++it; + } + _fd_events.erase(fd); +} + +void PollManager::updateFd(int fd, short events) { + for (size_t i = 0; i < _fds.size(); ++i) { + if (_fds[i].fd == fd) { + _fds[i].events = events; + break; + } + } + _fd_events[fd] = events; +} + +int PollManager::pollEvents(int timeout) { + return poll(_fds.data(), _fds.size(), timeout); +} + +const std::vector& PollManager::getFds() const { + return _fds; +} \ No newline at end of file diff --git a/sources/core/server.cpp b/sources/core/server.cpp index a43d6df..7c8cd5e 100644 --- a/sources/core/server.cpp +++ b/sources/core/server.cpp @@ -1,14 +1,14 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* server.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: omoudni +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/05/14 23:32:21 by omoudni ### ########.fr */ +/* Updated: 2025/05/19 20:16:00 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #include "color.hpp" #include "server.hpp" @@ -67,17 +67,48 @@ void Server::start() { close(server_fd); return; } + _pollManager.addFd(server_fd, POLLIN); std::cout << CLR_GREEN << "Server started on port " << this->_port << CLR_RESET << std::endl; std::cout << CLR_GREEN << "Waiting for clients..." << CLR_RESET << std::endl; - while (true) { - int client_fd = accept(server_fd, NULL, NULL); - if (client_fd == -1) { - std::cerr << CLR_RED << "Error: Failed to accept client" << CLR_RESET << std::endl; - continue; - } - std::cout << CLR_GREEN << "Client connected" << CLR_RESET << std::endl; - close(client_fd); - } + while (true) { + int n = _pollManager.pollEvents(); + if (n < 0) { + std::cerr << CLR_RED << "Poll error" << CLR_RESET << std::endl; + break; + } + const std::vector& fds = _pollManager.getFds(); + for (size_t i = 0; i < fds.size(); ++i) { + if (fds[i].revents & POLLIN) { + if (fds[i].fd == server_fd) { + // Accept new client + int client_fd = accept(server_fd, NULL, NULL); + if (client_fd != -1) { + _pollManager.addFd(client_fd, POLLIN); + std::cout << CLR_GREEN << "Client connected" << CLR_RESET << std::endl; + std::cout << "Welcome to IRC. Your client_id is: " << client_fd << std::endl; + } else { + std::cerr << CLR_RED << "Error: Failed to accept client" << CLR_RESET << std::endl; + + } + } else { + // Handle client communication + char buffer[1024]; + ssize_t bytes_received = recv(fds[i].fd, buffer, sizeof(buffer) - 1, 0); + if (bytes_received <= 0) { + // Client disconnected + // if it's negative, it means an error occurred, maybe print it with perror? + std::cout << CLR_RED << "Client disconnected" << CLR_RESET << std::endl; + close(fds[i].fd); + _pollManager.removeFd(fds[i].fd); + } else { + buffer[bytes_received] = '\0'; + std::cout << "Received: " << buffer << std::endl; + // Optionally: send response to client here + } + } + } + } + } close(server_fd); std::cout << CLR_GREEN << "Server stopped" << CLR_RESET << std::endl; }