diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..5c7247b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,7 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..11dd4e9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc-13 build active file", + "command": "/usr/bin/gcc-13", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 371ef02..3b55313 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(YourChat VERSION 0.1) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED True) include_directories(${PROJECT_SOURCE_DIR}) add_executable(yourchat main.cpp base.cpp config.cpp server.cpp room.cpp tools.cpp user.cpp) diff --git a/main.cpp b/main.cpp index e75d473..8f0401d 100755 --- a/main.cpp +++ b/main.cpp @@ -3,8 +3,8 @@ // main function int main(int, char **) { - Yc::Lib::Config *config = new Yc::Lib::Config(); - Yc::Lib::Server server(config); - server.run(); + auto config = std::make_shared(); + auto server = std::make_shared(config); + server->run(); return 0; } diff --git a/room.cpp b/room.cpp index 3cc1dab..8d64b39 100755 --- a/room.cpp +++ b/room.cpp @@ -12,11 +12,11 @@ namespace Yc { namespace Lib { - Room::Room(Server *parent, Json::Value roomParams) : - _parent(parent), - _blocked(false), - _stop(false), - _roundRunning(false) { + Room::Room(std::shared_ptr parent, Json::Value roomParams) : + _parent(std::move(parent)), + _blocked(false), + _stop(false), + _roundRunning(false) { _name = roomParams["name"].asString(); _password = roomParams["password"].asString(); std::vector allowedUsers; @@ -26,12 +26,10 @@ namespace Yc { _type = (RoomType)roomParams["type"].asInt(); _roundLength = roomParams["roundlength"].asInt(); _lastRoundEnd = std::time(NULL); - thread = new std::thread(&Room::run, this); + thread = std::make_unique(&Room::run, this); } - Room::~Room() { - delete thread; - } + Room::~Room() = default; void Room::run() { while (!_stop) { @@ -57,7 +55,7 @@ namespace Yc { if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers)) { return false; } - User *newUser = new User(this, _userName, color, socket); + auto newUser = std::make_shared(shared_from_this(), _userName, color, socket); _users.push_back(newUser); newUser->sendMsg(User::roomList, _parent->jsonRoomList(), "", ""); addMessage(User::system, "room_entered", newUser->name(), newUser->color()); @@ -65,10 +63,10 @@ namespace Yc { return true; } - bool Room::addUser(User *user, std::string password) { + bool Room::addUser(std::shared_ptr user, std::string password) { if (password == _password) { _users.push_back(user); - user->setParent(this); + user->setParent(shared_from_this()); _initRound(); return true; } @@ -76,7 +74,7 @@ namespace Yc { } bool Room::userNameExists(std::string userName) { - for (auto &user: _users) { + for (const auto &user: _users) { if (user->name() == userName) { return true; } @@ -85,24 +83,24 @@ namespace Yc { } void Room::removeUser(std::string _token, bool silent) { - for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { - if ((*user)->validateToken(_token)) { - _users.erase(user); + for (auto it = _users.begin(); it != _users.end(); ++it) { + if ((*it)->validateToken(_token)) { if (!silent) { - addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); + addMessage(User::system, "room_exit", (*it)->name(), (*it)->color()); } + _users.erase(it); break; } } } - void Room::removeUser(User *userToRemove, bool silent) { - for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { - if (*user == userToRemove) { - _users.erase(user); + void Room::removeUser(std::shared_ptr userToRemove, bool silent) { + for (auto it = _users.begin(); it != _users.end(); ++it) { + if (*it == userToRemove) { if (!silent) { - addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); + addMessage(User::system, "room_exit", (*it)->name(), (*it)->color()); } + _users.erase(it); break; } } @@ -129,15 +127,15 @@ namespace Yc { addMessage(type, getJsonString(messageText), userName, color); } - void Room::addUserWhenQueueEmpty(User *user) { + void Room::addUserWhenQueueEmpty(std::shared_ptr user) { while (_msgQueue.size() > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } _users.push_back(user); - user->setParent(this); + user->setParent(shared_from_this()); } - bool Room::userToNewRoom(User *user, std::string newRoom, std::string password) { + bool Room::userToNewRoom(std::shared_ptr user, std::string newRoom, std::string password) { return _parent->changeRoom(user, newRoom, password); } @@ -171,7 +169,7 @@ namespace Yc { return (_roundRunning || (_type & rounds) == rounds) && (_type & dice) == dice; } - unsigned int Room::addDice(User *user, int diceValue) { + unsigned int Room::addDice(std::shared_ptr user, int diceValue) { if (!canDice()) { return 1; } @@ -183,7 +181,6 @@ namespace Yc { _diceValues.push_back(std::make_pair(user, diceValue)); addMessage(User::dice, std::to_string(diceValue), user->name(), user->color()); return 0; - } bool Room::accessAllowed(std::string userName, std::string password) { @@ -223,13 +220,13 @@ namespace Yc { } void Room::_showDiceRoundResults() { - std::sort(_diceValues.begin(), _diceValues.end(), [=](std::pair val1, std::pair val2) { + std::sort(_diceValues.begin(), _diceValues.end(), [=](const std::pair, int>& val1, const std::pair, int>& val2) { return (val1.second > val2.second); }); Json::Value userList = Json::arrayValue; for (auto &user: _diceValues) { Json::Value entry = Json::objectValue; - entry["name"] = user.first; + entry["name"] = user.first->name(); entry["value"] = user.second; userList.append(entry); } diff --git a/room.h b/room.h index 2023cf7..29944f0 100755 --- a/room.h +++ b/room.h @@ -16,7 +16,7 @@ namespace Yc { class Server; - class Room: public Base { + class Room: public Base, public std::enable_shared_from_this { public: enum RoomType { none = 0, @@ -26,15 +26,15 @@ namespace Yc { password = 8 }; - Room(Server *parent, Json::Value roomParams); + Room(std::shared_ptr parent, Json::Value roomParams); ~Room(); void run(); std::string name(); bool addUser(std::string userName, std::string color, std::string password, int socket); - bool addUser(User *user, std::string password); + bool addUser(std::shared_ptr user, std::string password); bool userNameExists(std::string userName); void removeUser(std::string _token, bool silent = false); - void removeUser(User *user, bool silent = false); + void removeUser(std::shared_ptr user, bool silent = false); void setStop(); void addMessage(User::MsgType type, const char* messageText, std::string userName = "", std::string color = ""); void addMessage(User::MsgType type, std::string messageText, std::string userName = "", std::string color = ""); @@ -42,11 +42,11 @@ namespace Yc { RoomType type(); bool isType(RoomType type); bool canDice(); - unsigned int addDice(User *user, int diceValue); + unsigned int addDice(std::shared_ptr user, int diceValue); bool accessAllowed(std::string userName, std::string password); bool userIsInRoom(std::string userName); - void addUserWhenQueueEmpty(User *user); - bool userToNewRoom(User *user, std::string newRoom, std::string password); + void addUserWhenQueueEmpty(std::shared_ptr user); + bool userToNewRoom(std::shared_ptr user, std::string newRoom, std::string password); unsigned int flags(); Json::Value userList(); private: @@ -57,21 +57,21 @@ namespace Yc { std::string color; }; - Server *_parent; + std::shared_ptr _parent; std::string _name; std::string _password; std::vector _allowedUsers; RoomType _type; - std::vector _users; + std::vector> _users; bool _blocked; bool _stop; std::queue _msgQueue; - std::thread *thread; + std::unique_ptr thread; bool _roundRunning; time_t _roundStart; time_t _lastRoundEnd; int _roundLength; - std::vector> _diceValues; + std::vector, int>> _diceValues; void _handleDice(); void _startDiceRound(); void _endDiceRound(); diff --git a/server.cpp b/server.cpp index 8a427fe..84705db 100755 --- a/server.cpp +++ b/server.cpp @@ -15,9 +15,9 @@ namespace Yc { namespace Lib { - Server::Server(Yc::Lib::Config *config) : - _config(config), - _stop(false) { + Server::Server(std::shared_ptr config) : + _config(std::move(config)), + _stop(false) { struct sockaddr_in serverAddr; int opt = true; _socket = socket(AF_INET, SOCK_STREAM, 0); @@ -31,7 +31,7 @@ namespace Yc { std::cout << "bind not possible" << std::endl; exit(-1); } - createRooms(config->group("rooms")); + createRooms(_config->group("rooms")); } void Server::run() { @@ -49,14 +49,14 @@ namespace Yc { FD_ZERO(&fd); FD_SET(_socket, &fd); if (select(_maxSd + 1, &fd, NULL, NULL, &tv) > 0) { - std::async(std::launch::async, &Server::handleRequest, this); + std::thread(&Server::handleRequest, this).detach(); } } } std::vector Server::roomList() { std::vector list; - for (auto &room: _rooms) { + for (const auto &room: _rooms) { list.push_back(room->name()); } return list; @@ -82,7 +82,7 @@ namespace Yc { return false; } - bool Server::changeRoom(User *user, std::string newRoom, std::string password) { + bool Server::changeRoom(std::shared_ptr user, std::string newRoom, std::string password) { if (!roomAllowed(newRoom, user->name(), password)) { return false; } @@ -113,8 +113,9 @@ namespace Yc { } void Server::createRooms(Json::Value roomList) { + auto self = shared_from_this(); for (auto &room: roomList) { - Room *newRoom = new Room(this, room); + auto newRoom = std::make_shared(self, room); _rooms.push_back(newRoom); } } @@ -143,7 +144,7 @@ namespace Yc { } bool Server::userExists(std::string userName) { - for (auto &room: _rooms) { + for (const auto &room: _rooms) { if (room->userNameExists(userName)) { return true; } @@ -160,10 +161,10 @@ namespace Yc { close(userSocket); return; } - std::string room = data["room"].asString(); + std::string roomName = data["room"].asString(); bool added(false); for (auto &room: _rooms) { - if (room->name() == data["room"].asString()) { + if (room->name() == roomName) { if (room->addUser(data["name"].asString(), data["color"].asString(), data["password"].asString(), userSocket)) { added = true; break; diff --git a/server.h b/server.h index 27253b8..c4624e6 100755 --- a/server.h +++ b/server.h @@ -10,20 +10,20 @@ namespace Yc { namespace Lib { - class Server: public Base + class Server: public Base, public std::enable_shared_from_this { public: - Server(Yc::Lib::Config *config); + Server(std::shared_ptr config); void run(); std::vector roomList(); Json::Value jsonRoomList(); bool roomAllowed(std::string roomName, std::string userName, std::string password); - bool changeRoom(User *user, std::string newRoom, std::string password); + bool changeRoom(std::shared_ptr user, std::string newRoom, std::string password); private: int _socket; - Yc::Lib::Config *_config; + std::shared_ptr _config; bool _stop; - std::vector _rooms; + std::vector> _rooms; void createRooms(Json::Value roomList); void handleRequest(); void inputSwitcher(int userSocket, std::string input); diff --git a/user.cpp b/user.cpp index 14648e1..2b675f9 100755 --- a/user.cpp +++ b/user.cpp @@ -14,15 +14,15 @@ namespace Yc { namespace Lib { - User::User(Room *parent, std::string name, std::string color, int socket) : - _parent(parent), - _name(name), - _color(color), + User::User(std::shared_ptr parent, std::string name, std::string color, int socket) : + _parent(std::move(parent)), + _name(std::move(name)), + _color(std::move(color)), _socket(socket), _stop(false) { _token = Yc::Lib::Tools::generateRandomString(32); sendMsg(token, _token, "", ""); - thread = new std::thread(&User::checkerTask, this); + thread = std::make_unique(&User::checkerTask, this); } User::~User() { @@ -37,8 +37,8 @@ namespace Yc { return (token == _token); } - bool User::isUser(User *toValidate) { - return (toValidate == this); + bool User::isUser(std::shared_ptr toValidate) { + return (toValidate.get() == this); } void User::sendMsg(MsgType type, const char *message, std::string userName, std::string color) { @@ -94,8 +94,8 @@ namespace Yc { return _color; } - void User::setParent(Room *parent) { - _parent = parent; + void User::setParent(std::shared_ptr parent) { + _parent = std::move(parent); } void User::send(std::string out) { @@ -151,7 +151,7 @@ namespace Yc { } void User::doDice() { - switch (_parent->addDice(this, (rand() % 6) + 1)) { + switch (_parent->addDice(shared_from_this(), (rand() % 6) + 1)) { case 1: sendMsg(system, "dice_not_possible", "", ""); break; @@ -164,7 +164,7 @@ namespace Yc { } void User::changeRoom(std::string newRoom, std::string password) { - if (!_parent->userToNewRoom(this, newRoom, password)) { + if (!_parent->userToNewRoom(shared_from_this(), newRoom, password)) { sendMsg(User::system, "room_not_possible", "", ""); } } diff --git a/user.h b/user.h index 2a3ff96..852096e 100755 --- a/user.h +++ b/user.h @@ -11,7 +11,7 @@ namespace Yc { class Room; - class User: public Base { + class User: public Base, public std::enable_shared_from_this { public: enum MsgType { error = -1, @@ -26,26 +26,26 @@ namespace Yc { result = 9 }; - User(Room *parent, std::string name, std::string color, int socket); + User(std::shared_ptr parent, std::string name, std::string color, int socket); ~User(); std::string name() const; bool validateToken(std::string token); - bool isUser(User *toValidate); + bool isUser(std::shared_ptr toValidate); void sendMsg(MsgType type, std::string message, std::string userName, std::string color); void sendMsg(MsgType type, const char *message, std::string userName, std::string color); void sendMsg(MsgType type, Json::Value message, std::string userName, std::string color); void checkerTask(); void stop(); std::string color() const; - void setParent(Room *parent); + void setParent(std::shared_ptr parent); private: - Room *_parent; + std::shared_ptr _parent; std::string _name; std::string _color; int _socket; std::string _token; bool _stop; - std::thread *thread; + std::unique_ptr thread; void send(std::string out); void send(Json::Value out); void handleMessage(std::string message);