From b5b4c94f654d84433b38a5346b5a365cbbb9d51c Mon Sep 17 00:00:00 2001 From: Torsten Schulz Date: Fri, 21 Jul 2017 21:49:19 +0200 Subject: [PATCH] Receive and send messages --- .gitignore | 1 + YourChat.pro | 6 ++++-- base.cpp | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ base.h | 21 +++++++++++++++++++++ room.cpp | 23 ++++++++++++++--------- room.h | 5 +++-- server.cpp | 21 ++++++--------------- server.h | 3 ++- user.cpp | 46 ++++++++++++++++++++++++++++++++-------------- user.h | 10 +++++++++- 10 files changed, 144 insertions(+), 44 deletions(-) create mode 100644 base.cpp create mode 100644 base.h diff --git a/.gitignore b/.gitignore index 60d8303..9b3a42a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /tools.o /user.o /yourchat +*.o diff --git a/YourChat.pro b/YourChat.pro index b0563cf..18caadf 100644 --- a/YourChat.pro +++ b/YourChat.pro @@ -9,7 +9,8 @@ SOURCES += main.cpp \ server.cpp \ room.cpp \ user.cpp \ - tools.cpp + tools.cpp \ + base.cpp DISTFILES += \ config/chatconfig.json @@ -19,7 +20,8 @@ HEADERS += \ server.h \ room.h \ user.h \ - tools.h + tools.h \ + base.h LIBS += -ljsoncpp \ -lpthread diff --git a/base.cpp b/base.cpp new file mode 100644 index 0000000..8bf05dc --- /dev/null +++ b/base.cpp @@ -0,0 +1,52 @@ +#include "base.h" + +#include +#include +#include +#include +#include + +namespace Yc { + namespace Lib { + + std::string Base::getJsonString(Json::Value json) { + std::string outString; + std::stringstream outStream; + outStream << json; + return outStream.str(); + } + + void Base::send(int socket, std::string out) { + write(socket, out.c_str(), out.length()); + } + + void Base::send(int socket, Json::Value out) { + std::string outString = getJsonString(out); + send(socket, outString); + } + + std::string Base::readSocket(int socket) + { + std::string msg(""); + char buffer[256]; + bzero(buffer, 256); + while (int received = recv(socket, buffer, 255, 0) > 0) { + msg += std::string(buffer); + if (received < 255) { + break; + } + } + return msg; + } + + Json::Value Base::getJsonTree(std::string msg) { + Json::Value inputTree; + Json::CharReaderBuilder rbuilder; + std::unique_ptr const reader(rbuilder.newCharReader()); + JSONCPP_STRING inputJsonString(msg); + reader->parse(inputJsonString.data(), inputJsonString.data() + inputJsonString.size(), &inputTree, NULL); + return inputTree; + } + + } // namespace Lib +} // namespace Yc diff --git a/base.h b/base.h new file mode 100644 index 0000000..185b680 --- /dev/null +++ b/base.h @@ -0,0 +1,21 @@ +#ifndef YC_LIB_BASE_H +#define YC_LIB_BASE_H + +#include + +namespace Yc { + namespace Lib { + + class Base { + protected: + std::string getJsonString(Json::Value json); + void send(int socket, std::string out); + void send(int socket, Json::Value out); + std::string readSocket(int socket); + Json::Value getJsonTree(std::string msg); + }; + + } // namespace Lib +} // namespace Yc + +#endif // YC_LIB_BASE_H diff --git a/room.cpp b/room.cpp index 16d2023..96f16fd 100644 --- a/room.cpp +++ b/room.cpp @@ -18,6 +18,10 @@ namespace Yc { thread = new std::thread(&Room::run, this); } + Room::~Room() { + delete thread; + } + void Room::run() { while (!_stop) { if (_msgQueue.size() > 0 && !_blocked) { @@ -26,12 +30,12 @@ namespace Yc { Message message = _msgQueue.front(); _msgQueue.pop(); for (auto &user: _users) { - user.sendMsg(message.type, message.messageTr, message.userName, message.color); + user->sendMsg(message.type, message.messageTr, message.userName, message.color); } } _blocked = false; } - usleep(50000); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } @@ -39,14 +43,14 @@ namespace Yc { if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers)) { return false; } - User newUser(this, _userName, color, socket); + User *newUser = new User(this, _userName, color, socket); _users.push_back(newUser); - newUser.sendMsg(User::roomList, _parent->jsonRoomList(), "", ""); - addMessage(User::system, "room_entered", newUser.name(), newUser.color()); + newUser->sendMsg(User::roomList, _parent->jsonRoomList(), "", ""); + addMessage(User::system, "room_entered", newUser->name(), newUser->color()); return true; } - bool Room::addUser(User user, std::string password) { + bool Room::addUser(User *user, std::string password) { if (password == _password) { _users.push_back(user); return true; @@ -56,7 +60,7 @@ namespace Yc { bool Room::userNameExists(std::string userName) { for (auto &user: _users) { - if (user.name() == userName) { + if (user->name() == userName) { return true; } } @@ -64,9 +68,10 @@ namespace Yc { } void Room::removeUser(std::string _token) { - for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { - if (user->validateToken(_token)) { + for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { + if ((*user)->validateToken(_token)) { _users.erase(user); + break; } } } diff --git a/room.h b/room.h index 4d59676..6c928cf 100644 --- a/room.h +++ b/room.h @@ -16,10 +16,11 @@ namespace Yc { { public: Room(Server *parent, std::string name, std::string password = "", std::vector allowedUsers = std::vector()); + ~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(User *user, std::string password); bool userNameExists(std::string userName); void removeUser(std::string _token); void setStop(); @@ -36,7 +37,7 @@ namespace Yc { std::string _name; std::string _password; std::vector _allowedUsers; - std::vector _users; + std::vector _users; bool _blocked; bool _stop; std::queue _msgQueue; diff --git a/server.cpp b/server.cpp index 88b2b5b..11962db 100644 --- a/server.cpp +++ b/server.cpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -91,15 +90,7 @@ namespace Yc { } int flags = 1; setsockopt(userSock, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); - std::string msg(""); - char buffer[256]; - bzero(buffer, 256); - while (int received = recv(userSock, buffer, 255, 0) > 0) { - msg += std::string(buffer); - if (received < 255) { - break; - } - } + std::string msg = readSocket(userSock); if (msg == "") { return; } @@ -107,11 +98,7 @@ namespace Yc { } void Server::inputSwitcher(int userSocket, std::string input) { - Json::Value inputTree; - Json::CharReaderBuilder rbuilder; - std::unique_ptr const reader(rbuilder.newCharReader()); - JSONCPP_STRING inputJsonString(input); - reader->parse(inputJsonString.data(), inputJsonString.data() + inputJsonString.size(), &inputTree, NULL); + Json::Value inputTree = getJsonTree(input); if (inputTree["type"] == "init") { initUser(userSocket, inputTree); } @@ -128,6 +115,10 @@ namespace Yc { void Server::initUser(int userSocket, Json::Value data) { if (userExists(data["name"].asString())) { + Json::Value errorJson; + errorJson["type"] = User::error; + errorJson["message"] = "loggedin"; + send(userSocket, errorJson); close(userSocket); return; } diff --git a/server.h b/server.h index dc24d27..6504314 100644 --- a/server.h +++ b/server.h @@ -4,12 +4,13 @@ #include "config.h" #include #include "room.h" +#include "base.h" #include namespace Yc { namespace Lib { - class Server + class Server: public Base { public: Server(Yc::Lib::Config *config); diff --git a/user.cpp b/user.cpp index 6e7603f..0db60c7 100644 --- a/user.cpp +++ b/user.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include "room.h" @@ -23,7 +22,12 @@ namespace Yc { _stop(false) { _token = Yc::Lib::Tools::generateRandomString(32); sendMsg(token, _token, "", ""); - std::async(std::bind(&User::checkerTask, this)); + thread = new std::thread(&User::checkerTask, this); + } + + User::~User() { + delete thread; + _parent->addMessage(User::system, "leaved_chat", _name, _color); } std::string User::name() const { @@ -44,11 +48,7 @@ namespace Yc { sendMessage["message"] = message; sendMessage["userName"] = userName; sendMessage["color"] = color; - std::string outString; - std::stringstream outStream; - outStream << sendMessage; - outString = outStream.str(); - write(_socket, outString.c_str(), outString.length()); + send(sendMessage); } void User::sendMsg(User::MsgType type, Json::Value message, std::string userName, std::string color) { @@ -57,11 +57,7 @@ namespace Yc { sendMessage["message"] = message; sendMessage["userName"] = userName; sendMessage["color"] = color; - std::string outString; - std::stringstream outStream; - outStream << sendMessage; - outString = outStream.str(); - write(_socket, outString.c_str(), outString.length()); + send(sendMessage); } void User::checkerTask() { @@ -71,11 +67,19 @@ namespace Yc { FD_SET(_socket, &readSd); timeval tv; tv.tv_sec = 0; - tv.tv_usec = 100; - if (select(_socket + 1, &readSd, NULL, NULL, &tv) < 0 && errno != ETIMEDOUT) { + tv.tv_usec = 500; + int selectResult = select(_socket + 1, &readSd, NULL, NULL, &tv); + std::cout << selectResult << "/" << FD_ISSET(_socket, &readSd) << std::endl; + if (selectResult == 1 && FD_ISSET(_socket, &readSd) == 1) { _parent->removeUser(_token); _stop = true; } + std::string msg = readSocket(_socket); + if (msg == "") { + continue; + } + std::cout << msg << std::endl; + handleMessage(msg); } } @@ -87,5 +91,19 @@ namespace Yc { return _color; } + void User::send(std::string out) { + Base::send(_socket, out); + } + + void User::send(Json::Value out) { + Base::send(_socket, out); + } + + void User::handleMessage(std::string message) { + Json::Value jsonTree = getJsonTree(message); + if (jsonTree["type"].asString() == "message") { + _parent->addMessage(User::message, jsonTree["message"].asString(), _name, _color); + } + } } // namespace Lib } // namespace Yc diff --git a/user.h b/user.h index c6b5019..30ddcb2 100644 --- a/user.h +++ b/user.h @@ -3,15 +3,18 @@ #include #include +#include +#include "base.h" namespace Yc { namespace Lib { class Room; - class User { + class User: public Base { public: enum MsgType { + error = -1, token = 1, userListe = 2, roomList = 3, @@ -20,6 +23,7 @@ namespace Yc { }; User(Room *parent, std::string name, std::string color, int socket); + ~User(); std::string name() const; bool validateToken(std::string token); bool isUser(User *toValidate); @@ -35,6 +39,10 @@ namespace Yc { int _socket; std::string _token; bool _stop; + std::thread *thread; + void send(std::string out); + void send(Json::Value out); + void handleMessage(std::string message); }; } // namespace Lib