Receive and send messages
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -8,3 +8,4 @@
|
||||
/tools.o
|
||||
/user.o
|
||||
/yourchat
|
||||
*.o
|
||||
|
||||
@@ -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
|
||||
|
||||
52
base.cpp
Normal file
52
base.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
#include "base.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <memory>
|
||||
|
||||
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<Json::CharReader> const reader(rbuilder.newCharReader());
|
||||
JSONCPP_STRING inputJsonString(msg);
|
||||
reader->parse(inputJsonString.data(), inputJsonString.data() + inputJsonString.size(), &inputTree, NULL);
|
||||
return inputTree;
|
||||
}
|
||||
|
||||
} // namespace Lib
|
||||
} // namespace Yc
|
||||
21
base.h
Normal file
21
base.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef YC_LIB_BASE_H
|
||||
#define YC_LIB_BASE_H
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
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
|
||||
23
room.cpp
23
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<User>::iterator user = _users.begin(); user != _users.end(); ++user) {
|
||||
if (user->validateToken(_token)) {
|
||||
for (std::vector<User*>::iterator user = _users.begin(); user != _users.end(); ++user) {
|
||||
if ((*user)->validateToken(_token)) {
|
||||
_users.erase(user);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
room.h
5
room.h
@@ -16,10 +16,11 @@ namespace Yc {
|
||||
{
|
||||
public:
|
||||
Room(Server *parent, std::string name, std::string password = "", std::vector<std::string> allowedUsers = std::vector<std::string>());
|
||||
~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<std::string> _allowedUsers;
|
||||
std::vector<User> _users;
|
||||
std::vector<User*> _users;
|
||||
bool _blocked;
|
||||
bool _stop;
|
||||
std::queue<Message> _msgQueue;
|
||||
|
||||
21
server.cpp
21
server.cpp
@@ -6,7 +6,6 @@
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <functional>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <json/json.h>
|
||||
#include <iostream>
|
||||
@@ -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<Json::CharReader> 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;
|
||||
}
|
||||
|
||||
3
server.h
3
server.h
@@ -4,12 +4,13 @@
|
||||
#include "config.h"
|
||||
#include <vector>
|
||||
#include "room.h"
|
||||
#include "base.h"
|
||||
#include <json/value.h>
|
||||
|
||||
namespace Yc {
|
||||
namespace Lib {
|
||||
|
||||
class Server
|
||||
class Server: public Base
|
||||
{
|
||||
public:
|
||||
Server(Yc::Lib::Config *config);
|
||||
|
||||
46
user.cpp
46
user.cpp
@@ -3,7 +3,6 @@
|
||||
#include <tools.h>
|
||||
#include <json/json.h>
|
||||
#include <unistd.h>
|
||||
#include <future>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#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
|
||||
|
||||
10
user.h
10
user.h
@@ -3,15 +3,18 @@
|
||||
|
||||
#include <string>
|
||||
#include <json/json.h>
|
||||
#include <thread>
|
||||
#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
|
||||
|
||||
Reference in New Issue
Block a user