Receive and send messages

This commit is contained in:
Torsten Schulz
2017-07-21 21:49:19 +02:00
parent 922ee7ac12
commit b5b4c94f65
10 changed files with 144 additions and 44 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@
/tools.o
/user.o
/yourchat
*.o

View File

@@ -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
View 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
View 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

View File

@@ -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
View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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
View File

@@ -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