#include "server.h" #include #include #include #include #include #include #include #include #include #include #include namespace Yc { namespace Lib { 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); setsockopt(_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); int flags = 1; setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(1235); if (bind(_socket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { std::cout << "bind not possible" << std::endl; exit(-1); } // createRooms wird jetzt außerhalb des Konstruktors aufgerufen } void Server::run() { if (listen(_socket, 5) < 0) { std::cout << "listen not possible" << std::endl; exit(-1); } timeval origTv; origTv.tv_sec = 5; origTv.tv_usec = 0; int _maxSd = _socket; while (!_stop) { timeval tv(origTv); fd_set fd; FD_ZERO(&fd); FD_SET(_socket, &fd); if (select(_maxSd + 1, &fd, NULL, NULL, &tv) > 0) { std::thread(&Server::handleRequest, this).detach(); } } } std::vector Server::roomList() { std::vector list; for (const auto &room: _rooms) { list.push_back(room->name()); } return list; } Json::Value Server::jsonRoomList() { Json::Value list; for (auto &room: _rooms) { Json::Value roomJson = Json::objectValue; roomJson["name"] = room->name(); roomJson["flags"] = room->flags(); list.append(roomJson); } return list; } bool Server::roomAllowed(std::string roomName, std::string userName, std::string password){ for (auto &room: _rooms) { if (room->name() == roomName && room->accessAllowed(userName, password)) { return true; } } return false; } bool Server::changeRoom(std::shared_ptr user, std::string newRoom, std::string password) { if (!roomAllowed(newRoom, user->name(), password)) { return false; } Json::Value userMsg = Json::objectValue; userMsg["tr"] = "room_change_user"; userMsg["to"] = newRoom; for (auto &room: _rooms) { if (room->userIsInRoom(user->name())) { room->removeUser(user); Json::Value msg = Json::objectValue; msg["tr"] = "room_change_to"; msg["to"] = newRoom; userMsg["from"] = room->name(); room->addMessage(User::system, msg, user->name(), user->color()); } } user->sendMsg(User::system, userMsg, "", ""); for (auto &room: _rooms) { if (room->name() == newRoom) { Json::Value msg = Json::objectValue; msg["tr"] = "room_change_to"; msg["from"] = userMsg["from"]; room->addMessage(User::system, msg, user->name(), user->color()); room->addUserWhenQueueEmpty(user); } } return true; } void Server::createRooms(Json::Value roomList) { auto self = shared_from_this(); for (auto &room: roomList) { auto newRoom = std::make_shared(self, room); _rooms.push_back(newRoom); } } void Server::handleRequest() { struct sockaddr_in sockAddr; socklen_t sockAddrLen = sizeof(sockAddr); int userSock = accept(_socket, (struct sockaddr *)&sockAddr, &sockAddrLen); if (userSock < 0) { return; } int flags = 1; setsockopt(userSock, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); std::string msg = readSocket(userSock); if (msg == "") { return; } inputSwitcher(userSock, msg); } void Server::inputSwitcher(int userSocket, std::string input) { Json::Value inputTree = getJsonTree(input); if (inputTree["type"] == "init") { initUser(userSocket, inputTree); } } bool Server::userExists(std::string userName) { for (const auto &room: _rooms) { if (room->userNameExists(userName)) { return true; } } return false; } 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; } std::string roomName = data["room"].asString(); bool added(false); for (auto &room: _rooms) { if (room->name() == roomName) { if (room->addUser(data["name"].asString(), data["color"].asString(), data["password"].asString(), userSocket)) { added = true; break; } } } if (!added) { close(userSocket); } } } // namespace Lib } // namespace Yp