diff --git a/.vscode/settings.json b/.vscode/settings.json index 26180ef..18ad11c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -81,6 +81,9 @@ "expected": "cpp", "complex": "cpp", "__config": "cpp", - "ranges": "cpp" + "ranges": "cpp", + "valarray": "cpp", + "__tree": "cpp", + "map": "cpp" } } \ No newline at end of file diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt index 77958c2..2ddfad7 100644 --- a/Client/CMakeLists.txt +++ b/Client/CMakeLists.txt @@ -33,6 +33,7 @@ FetchContent_MakeAvailable(JSONCPP) file(GLOB_RECURSE additional_sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/../impl/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" ) add_executable(${PROJECT_NAME} diff --git a/Client/include/ClientManager/ClientManager.hpp b/Client/include/ClientManager/ClientManager.hpp new file mode 100644 index 0000000..4ecf85b --- /dev/null +++ b/Client/include/ClientManager/ClientManager.hpp @@ -0,0 +1,101 @@ +#pragma once +#include "Utils/ThreadPool.hpp" +#include "Utils/ConfigManager.hpp" +#include "Socket/IOCP.hpp" +#include "Packet/Packet.hpp" + +namespace Chattr { + +class ClientManager { +public: + void _IOCPClient(ThreadPool* thread, IOCPPASSINDATA* data); + + PacketSet packetParser(Packet Packet); + + template + void init(_Callable _IOCPClient) { + auto config = ConfigManager::load(); + log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount); + threadPool_.init(0); + iocp_.init(&threadPool_, _IOCPClient); + + struct Address serveraddr; + if (config.ipVersion == 4) { + sock_.init(AF_INET); + serveraddr.set(AF_INET, config.IP, config.Port); + } + else if (config.ipVersion == 6) { + sock_.init(AF_INET6); + serveraddr.set(AF_INET6, config.IP, config.Port); + } + + if (sock_.connect(serveraddr) == INVALID_SOCKET) { + spdlog::error("{}", strerror(errno)); + return; + } + + data_ = new IOCPPASSINDATA; + ::memset(&data_->overlapped, 0, sizeof(OVERLAPPED)); + data_->socket = std::make_shared(std::move(sock_)); + data_->recvbytes = data_->sendbytes = 0; + data_->wsabuf.buf = data_->buf; + data_->wsabuf.len = 1500; + data_->IOCPInstance = &iocp_; + iocp_.registerSocket(data_); + + spdlog::info("Connection established from [{}]", (std::string)serveraddr); + } + + void init() { + init([this](ThreadPool* thread, IOCPPASSINDATA* data) { + this->_IOCPClient(thread, data); + }); + } + + void processresponsePacket(ResponsePacket responsePacket, IOCPPASSINDATA* data); + void processRoomCreateResponsePacket(RoomCreateResponsePacket roomCreateResponsePacket, IOCPPASSINDATA* data); + void processRoomListResponse(RoomListResponsePacket roomListResponsePacket, IOCPPASSINDATA* data); + void processRoomJoinResponsePacket(RoomJoinResponsePacket roomJoinResponsePacket, IOCPPASSINDATA* data); + void processRoomExitResponsePacket(RoomExitResponsePacket roomExitResponsePacket, IOCPPASSINDATA* data); + void processUsersListResponsePacket(UsersListResponsePacket usersListResponsePacket, IOCPPASSINDATA* data); + void processDataPostPacket(DataPostPacket dataPostPacket, IOCPPASSINDATA* data); + void processContinuePacket(ContinuePacket continuePacket, IOCPPASSINDATA* data); + + void registerUser(std::string userName); + void deleteUser(Snowflake UID); + std::vector> getUserList(); + + Snowflake createRoom(std::string roomName); + void deleteRoom(Snowflake RID); + std::vector> getRoomList(); + + void joinRoom(Snowflake UID, Snowflake RID); + void exitRoom(Snowflake UID, Snowflake RID); + + void run(); +private: + ThreadPool threadPool_; + IOCP iocp_; + + Snowflake myID_; + Snowflake myRoomID_; + + IOCPPASSINDATA* data_; + + bool inRoom_ = false; + + TCPSocket sock_; + + std::mutex resourceMutex_; + + std::unordered_map roomNames_; + + std::unordered_map>> rooms_; + + std::unordered_map> UID2userSocket_; + std::unordered_map, Snowflake> userSocket2UID_; + + std::unordered_map userNames_; +}; + +} \ No newline at end of file diff --git a/Client/src/ClientManager/ClientManager.cpp b/Client/src/ClientManager/ClientManager.cpp new file mode 100644 index 0000000..c904a50 --- /dev/null +++ b/Client/src/ClientManager/ClientManager.cpp @@ -0,0 +1,488 @@ +#include "ClientManager/ClientManager.hpp" +#include "Utils/ConfigManager.hpp" +#include "Utils/StringTokenizer.hpp" +#include "Socket/Log.hpp" +#include + +namespace Chattr { + +void ClientManager::_IOCPClient(Chattr::ThreadPool* thread, Chattr::IOCPPASSINDATA* data) { + Chattr::Packet pack; + int packetSize = data->transferredbytes; + + if (data->event == IOCPEVENT::WRITE && data->transferredbytes >= data->wsabuf.len) { + data->event = IOCPEVENT::READ; + data->wsabuf.len = 1500; + data->IOCPInstance->recv(data, 1); + return; + } + + memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len); + + std::uint16_t packetLength = ::ntohs(pack.__data.packetLength); + + if (data->event == IOCPEVENT::READ && data->transferredbytes < packetLength + 8) { + data->IOCPInstance->recv(data, 1); + data->wsabuf.len = 1500; + return; + } + + pack.convToH(); + PacketSet packetSet = packetParser(pack); + pack.convToN(); + switch (packetSet) { + case PacketSet::LOGINRESPONSE: + case PacketSet::ROOMCREATERESPONSE: + case PacketSet::ROOMLISTRESPONSE: + case PacketSet::ROOMJOINRESPONSE: + case PacketSet::ROOMEXITRESPONSE: + case PacketSet::USERSLISTRESPONSE: + case PacketSet::RESPONSE: { + ResponsePacket responsePacket; + std::memcpy(&responsePacket.serialized, &pack.serialized, 8 + packetLength); + responsePacket.convToH(); + processresponsePacket(responsePacket, data); + } + break; + case PacketSet::DATAPOST: { + DataPostPacket dataPostPacket; + std::memcpy(&dataPostPacket.serialized, &pack.serialized, 8 + packetLength); + dataPostPacket.convToH(); + processDataPostPacket(dataPostPacket, data); + } + break; + case PacketSet::CONTINUE: { + ContinuePacket continuePacket; + std::memcpy(&continuePacket.serialized, &pack.serialized, 8 + packetLength); + continuePacket.convToH(); + processContinuePacket(continuePacket, data); + } + break; + case PacketSet::INVALID: + default: { + } + break; + } +} + +PacketSet ClientManager::packetParser(Packet Packet) { + if (Packet.__data.packetLength < 0 || Packet.__data.packetLength > 1492) + return PacketSet::INVALID; + + switch (Packet.__data.packetType) { + case PacketCategory::PACKET_POST: + if (Packet.__data.requestType != RequestType::DATA) { + return PacketSet::INVALID; + } + switch (Packet.__data.dataType) { + case DataType::TEXT: + case DataType::BINARY: + return PacketSet::DATAPOST; + default: + return PacketSet::INVALID; + } + break; + case PacketCategory::PACKET_REQUEST: + switch (Packet.__data.requestType) { + case RequestType::LOGIN: + return PacketSet::LOGINREQUEST; + case RequestType::ROOM_CREATE: + return PacketSet::ROOMCREATEREQUEST; + case RequestType::ROOM_LIST: + return PacketSet::ROOMLISTREQUEST; + case RequestType::ROOM_JOIN: + return PacketSet::ROOMJOINREQUEST; + case RequestType::ROOM_EXIT: + return PacketSet::ROOMEXITREQUEST; + case RequestType::USERS_LIST: + return PacketSet::USERSLISTREQUEST; + case RequestType::DATA: + return PacketSet::INVALID; + } + break; + case PacketCategory::PACKET_RESPONSE: + switch (Packet.__data.requestType) { + case RequestType::LOGIN: + return PacketSet::LOGINRESPONSE; + case RequestType::ROOM_CREATE: + return PacketSet::ROOMCREATERESPONSE; + case RequestType::ROOM_LIST: + return PacketSet::ROOMLISTRESPONSE; + case RequestType::ROOM_JOIN: + return PacketSet::ROOMJOINRESPONSE; + case RequestType::ROOM_EXIT: + return PacketSet::ROOMEXITRESPONSE; + case RequestType::USERS_LIST: + return PacketSet::USERSLISTRESPONSE; + case RequestType::DATA: + return PacketSet::RESPONSE; + default: + return PacketSet::INVALID; + } + break; + case PacketCategory::PACKET_CONTINUE: + return PacketSet::CONTINUE; + default: + return PacketSet::INVALID; + } + + return PacketSet::INVALID; +} + +void ClientManager::processresponsePacket(ResponsePacket responsePacket, IOCPPASSINDATA* data) { + responsePacket; + // std::string userName( + // (char*)loginResponsePacket.__data.data, + // loginResponsePacket.__data.packetLength); + // registerUser(userName); + + // LoginResponsePacket loginResponsePacket; + // loginResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // loginResponsePacket.__data.requestType = Chattr::RequestType::LOGIN; + // loginResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // loginResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(Snowflake); + // loginResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + // Snowflake yourId = userSocket2UID_[data->socket]; + // ::memcpy(loginResponsePacket.__data.yourId, &yourId, sizeof(Snowflake)); + + // loginResponsePacket.convToN(); + // memcpy(data->wsabuf.buf, loginResponsePacket.serialized, 18); + // data->sendbytes = 18; + // data->wsabuf.len = 18; + // data->IOCPInstance->send(data, 1, 0); +} + +void ClientManager::processRoomCreateResponsePacket(RoomCreateResponsePacket roomCreateResponsePacket, Chattr::IOCPPASSINDATA* data) { + // std::string roomName( + // (char*)roomCreateResponsePacket.__data.data, + // roomCreateResponsePacket.__data.packetLength); + // Snowflake RID = createRoom(roomName); + + // RoomCreateResponsePacket roomCreateResponsePacket; + // roomCreateResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // roomCreateResponsePacket.__data.requestType = Chattr::RequestType::ROOM_CREATE; + // roomCreateResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // roomCreateResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(Snowflake); + // roomCreateResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + // ::memcpy(roomCreateResponsePacket.__data.createdRoomId, &RID, sizeof(Snowflake)); + + // roomCreateResponsePacket.convToN(); + // memcpy(data->wsabuf.buf, roomCreateResponsePacket.serialized, 18); + // data->sendbytes = 18; + // data->wsabuf.len = 18; + // data->IOCPInstance->send(data, 1, 0); +} + +void ClientManager::processRoomListResponse(RoomListResponsePacket roomListResponsePacket, Chattr::IOCPPASSINDATA* data) { + // auto roomsList = getRoomList(); + + // for (auto room : roomsList) { + // RoomListResponsePacket roomListResponsePacket; + // roomListResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // roomListResponsePacket.__data.requestType = Chattr::RequestType::ROOM_LIST; + // roomListResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // roomListResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(std::uint32_t) + sizeof(Snowflake) + room.second.size(); + // roomListResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + // roomListResponsePacket.__data.roomCount = roomsList.size(); + // ::memcpy(roomListResponsePacket.__data.roomId, &room.first, sizeof(Snowflake)); + // ::memcpy(roomListResponsePacket.__data.name, room.second.c_str(), room.second.size()); + + // int packetLength = roomListResponsePacket.__data.packetLength; + + // Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + // ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + // ptr->socket = data->socket; + // ptr->recvbytes = ptr->sendbytes = 0; + // ptr->wsabuf.buf = ptr->buf; + // ptr->wsabuf.len = packetLength + 8; + // ptr->IOCPInstance = data->IOCPInstance; + + // roomListResponsePacket.convToN(); + // memcpy(ptr->wsabuf.buf, roomListResponsePacket.serialized, packetLength + 8); + // data->sendbytes = packetLength + 8; + // data->IOCPInstance->send(ptr, 1, 0); + // } +} + +void ClientManager::processRoomJoinResponsePacket(RoomJoinResponsePacket roomJoinResponsePacket, Chattr::IOCPPASSINDATA* data) { + // Snowflake myID, roomID; + // ::memcpy(&myID.snowflake, roomJoinResponsePacket.__data.myId, sizeof(Snowflake)); + // ::memcpy(&roomID.snowflake, roomJoinResponsePacket.__data.roomId, sizeof(Snowflake)); + + // joinRoom(myID, roomID); + + // RoomJoinResponsePacket roomJoinResponsePacket; + // roomJoinResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // roomJoinResponsePacket.__data.requestType = Chattr::RequestType::ROOM_JOIN; + // roomJoinResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // roomJoinResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + // roomJoinResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + // int packetLength = roomJoinResponsePacket.__data.packetLength; + + // roomJoinResponsePacket.convToN(); + // ::memcpy(data->wsabuf.buf, roomJoinResponsePacket.serialized, 10); + // data->sendbytes = 10; + // data->wsabuf.len = 10; + // data->IOCPInstance->send(data, 1, 0); +} + +void ClientManager::processRoomExitResponsePacket(RoomExitResponsePacket roomExitResponsePacket, Chattr::IOCPPASSINDATA* data) { + // Snowflake myID, roomID; + // ::memcpy(&myID.snowflake, roomExitResponsePacket.__data.myId, sizeof(Snowflake)); + // ::memcpy(&roomID.snowflake, roomExitResponsePacket.__data.roomId, sizeof(Snowflake)); + + // exitRoom(myID, roomID); + + // RoomExitResponsePacket roomExitResponsePacket; + // roomExitResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // roomExitResponsePacket.__data.requestType = Chattr::RequestType::ROOM_EXIT; + // roomExitResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // roomExitResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + // roomExitResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + // int packetLength = roomExitResponsePacket.__data.packetLength; + + // roomExitResponsePacket.convToN(); + // ::memcpy(data->wsabuf.buf, roomExitResponsePacket.serialized, 10); + // data->sendbytes = 10; + // data->wsabuf.len = 10; + // data->IOCPInstance->send(data, 1, 0); +} + +void ClientManager::processUsersListResponsePacket(UsersListResponsePacket usersListResponsePacket, Chattr::IOCPPASSINDATA* data) { + // auto usersList = getUserList(); + + // for (auto user : usersList) { + // UsersListResponsePacket usersListResponsePacket; + // usersListResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + // usersListResponsePacket.__data.requestType = Chattr::RequestType::USERS_LIST; + // usersListResponsePacket.__data.dataType = Chattr::DataType::BINARY; + // usersListResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(std::uint32_t) + sizeof(Snowflake) + user.second.size(); + // usersListResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + // usersListResponsePacket.__data.usersCount = usersList.size(); + // ::memcpy(usersListResponsePacket.__data.userId, &user.first, sizeof(Snowflake)); + // ::memcpy(usersListResponsePacket.__data.name, user.second.c_str(), user.second.size()); + + // int packetLength = usersListResponsePacket.__data.packetLength; + + // Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + // ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + // ptr->socket = data->socket; + // ptr->recvbytes = ptr->sendbytes = 0; + // ptr->wsabuf.buf = ptr->buf; + // ptr->wsabuf.len = packetLength + 8; + // ptr->IOCPInstance = data->IOCPInstance; + + // usersListResponsePacket.convToN(); + // memcpy(ptr->wsabuf.buf, usersListResponsePacket.serialized, packetLength + 8); + // data->sendbytes = packetLength + 8; + // data->IOCPInstance->send(ptr, 1, 0); + // } +} + +void ClientManager::processDataPostPacket(DataPostPacket dataPostPacket, IOCPPASSINDATA* data) { + Snowflake destID; + ::memcpy(&destID.snowflake, dataPostPacket.__data.destId, sizeof(Snowflake)); + + std::vector> destinationSockets; + + if (userNames_.find(destID) != userNames_.end()) + destinationSockets.push_back(UID2userSocket_[destID]); + else + for (auto user : rooms_[destID]) + destinationSockets.push_back(user.second); + + spdlog::info("Received [{}] from : [{}] to : [{}]", + std::string((char*)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t) * 5)), + (std::string)data->socket->remoteAddr, + destID.snowflake); + + ResponsePacket responsePacket; + responsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + responsePacket.__data.requestType = Chattr::RequestType::DATA; + responsePacket.__data.dataType = Chattr::DataType::TEXT; + responsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + responsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + responsePacket.convToN(); + memcpy(data->wsabuf.buf, responsePacket.serialized, 10); + data->sendbytes = 10; + data->wsabuf.len = 10; + data->IOCPInstance->send(data, 1, 0); + + int packetLength = dataPostPacket.__data.packetLength; + + for (auto dest : destinationSockets) { + + Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + ptr->socket = dest; + ptr->recvbytes = ptr->sendbytes = 0; + ptr->wsabuf.buf = ptr->buf; + ptr->wsabuf.len = packetLength + 6; + ptr->IOCPInstance = data->IOCPInstance; + + dataPostPacket.convToN(); + memcpy(ptr->wsabuf.buf, dataPostPacket.serialized, packetLength + 6); + data->sendbytes = packetLength + 6; + data->IOCPInstance->send(ptr, 1, 0); + } +} + +void ClientManager::processContinuePacket(ContinuePacket continuePacket, IOCPPASSINDATA* data) { + Snowflake destID; + ::memcpy(&destID.snowflake, continuePacket.__data.destId, sizeof(Snowflake)); + + std::vector> destinationSockets; + + if (userNames_.find(destID) != userNames_.end()) + destinationSockets.push_back(UID2userSocket_[destID]); + else + for (auto user : rooms_[destID]) + destinationSockets.push_back(user.second); + + spdlog::info("Received [{}] from : [{}] to : [{}]", + std::string((char*)continuePacket.__data.data, continuePacket.__data.packetLength - (sizeof(std::uint16_t) * 5)), + (std::string)data->socket->remoteAddr, + destID.snowflake); + + ResponsePacket responsePacket; + responsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + responsePacket.__data.requestType = Chattr::RequestType::DATA; + responsePacket.__data.dataType = Chattr::DataType::TEXT; + responsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + responsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + responsePacket.convToN(); + memcpy(data->wsabuf.buf, responsePacket.serialized, 10); + data->sendbytes = 10; + data->wsabuf.len = 10; + data->IOCPInstance->send(data, 1, 0); + + int packetLength = continuePacket.__data.packetLength; + + for (auto dest : destinationSockets) { + Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + ptr->socket = dest; + ptr->recvbytes = ptr->sendbytes = 0; + ptr->wsabuf.buf = ptr->buf; + ptr->wsabuf.len = packetLength + 6; + ptr->IOCPInstance = data->IOCPInstance; + + continuePacket.convToN(); + memcpy(ptr->wsabuf.buf, continuePacket.serialized, packetLength + 6); + data->sendbytes = packetLength + 6; + data->IOCPInstance->send(ptr, 1, 0); + } +} + +void ClientManager::registerUser(std::string userName) { + Chattr::LoginRequestPacket loginRequestPacket; + loginRequestPacket.__data.packetType = Chattr::PacketCategory::PACKET_REQUEST; + loginRequestPacket.__data.requestType = Chattr::RequestType::LOGIN; + loginRequestPacket.__data.dataType = Chattr::DataType::BINARY; + loginRequestPacket.__data.packetLength = userName.size(); + memcpy(loginRequestPacket.__data.data, userName.c_str(), userName.size()); + + int packetLength = loginRequestPacket.__data.packetLength; + + data_->recvbytes = data_->sendbytes = 0; + data_->wsabuf.len = packetLength + 8; + + loginRequestPacket.convToN(); + memcpy(data_->wsabuf.buf, loginRequestPacket.serialized, packetLength + 8); + data_->sendbytes = packetLength + 8; + iocp_.send(data_, 1, 0, true); +} + +void ClientManager::deleteUser(Snowflake UID) { + std::lock_guard lock(resourceMutex_); + userNames_.erase(UID); + std::shared_ptr sock = UID2userSocket_[UID]; + UID2userSocket_.erase(UID); + userSocket2UID_.erase(sock); +} + +std::vector> ClientManager::getUserList() { + std::lock_guard lock(resourceMutex_); + std::vector> userList; + userList.reserve(userNames_.size()); + + for (auto user : userNames_) + userList.push_back(user); + + return userList; +} + +Snowflake ClientManager::createRoom(std::string roomName) { + std::lock_guard lock(resourceMutex_); + Snowflake RID = GenerateID(); + roomNames_[RID] = roomName; + rooms_[RID] = std::unordered_map>(); + return RID; +} + +void ClientManager::deleteRoom(Snowflake RID) { + std::lock_guard lock(resourceMutex_); + roomNames_.erase(RID); + rooms_.erase(RID); +} + +std::vector> ClientManager::getRoomList() { + std::lock_guard lock(resourceMutex_); + std::vector> roomList; + roomList.reserve(roomNames_.size()); + + for (auto user : roomNames_) + roomList.push_back(user); + + return roomList; +} + +void ClientManager::joinRoom(Snowflake UID, Snowflake RID) { + std::lock_guard lock(resourceMutex_); + std::shared_ptr sock = UID2userSocket_[UID]; + rooms_[RID][UID] = sock; +} + +void ClientManager::exitRoom(Snowflake UID, Snowflake RID) { + std::lock_guard lock(resourceMutex_); + rooms_[RID].erase(UID); +} + +void ClientManager::run() { + StringTokenizer tokenizer; + std::string nickname; + + std::cout << "Please enter your nickname: "; + std::getline(std::cin, nickname); + tokenizer.set(nickname.c_str(), nickname.size()); + + registerUser(tokenizer.get()[0]); + + std::cout << "Commads:" << std::endl; + std::cout << "/w : Send direct message to specified user" << std::endl; + std::cout << "/join : Enter specified room" << std::endl; + std::cout << "/exit : Exit current room" << std::endl; + std::cout << "/create : Create room" << std::endl; + std::cout << "/list : Print all registred users" << std::endl; + std::cout << "/exit : Terminate this program (When you are not in room)" << std::endl; + + while (true) { + std::string input; + + if (inRoom_) { + std::cout << "[" << nickname << "@" << roomNames_[myRoomID_] << "]" << " "; + } + else { + std::cout << "[" << nickname << "]" << " "; + } + + std::getline(std::cin, input); + tokenizer.set(input.c_str(), input.size()); + } +} + +} \ No newline at end of file diff --git a/Client/src/Socket/Log.cpp b/Client/src/Socket/Log.cpp new file mode 100644 index 0000000..6f67a53 --- /dev/null +++ b/Client/src/Socket/Log.cpp @@ -0,0 +1,25 @@ +#include "Socket/Log.hpp" + +#include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/sinks/rotating_file_sink.h" +#ifdef _WIN32 +#include "spdlog/sinks/msvc_sink.h" +#endif + +#include "precomp.hpp" + +namespace Chattr::log { + +void setDefaultLogger(spdlog::level::level_enum logLevel, gsl::czstring logFileName, std::uint32_t logFileSize, std::uint32_t logFileCount) { + std::vector sinks; + sinks.push_back(std::make_shared()); + sinks.push_back(std::make_shared(logFileName, logFileSize, logFileCount, false)); +#ifdef _WIN32 + sinks.push_back(std::make_shared()); +#endif + auto chatteringLogger = std::make_shared("Chattering Logger", begin(sinks), end(sinks)); + chatteringLogger->set_level(logLevel); + spdlog::set_default_logger(chatteringLogger); +} + +} \ No newline at end of file diff --git a/Client/src/Utils/ConfigManager.cpp b/Client/src/Utils/ConfigManager.cpp new file mode 100644 index 0000000..430d63a --- /dev/null +++ b/Client/src/Utils/ConfigManager.cpp @@ -0,0 +1,56 @@ +#include "Utils/ConfigManager.hpp" +#include "precomp.hpp" +#include +#include +#include +#include + +namespace Chattr { +ConfigManager::Config ConfigManager::load() { + Config config; + + std::ifstream configfile("config.json", std::ifstream::binary); + if (!configfile.is_open()) { + std::ofstream defaultConfig("config.json", std::ios::out); + config.configJsonRoot["IP Version"] = 6; + config.configJsonRoot["IP"] = "::1"; + config.configJsonRoot["Port"] = 9010; + config.configJsonRoot["LogLevel"] = 1; + config.configJsonRoot["LogfileName"] = "Chattering.log"; + config.configJsonRoot["LogfileSize"] = UINT32_MAX; + config.configJsonRoot["LogfileCount"] = 5; + defaultConfig << config.configJsonRoot; + defaultConfig.close(); + spdlog::critical("\"config.json\" is missing. Default configuration has been written."); + } + try { + if (configfile.is_open()) + configfile >> config.configJsonRoot; + + config.ipVersion = config.configJsonRoot["IP Version"].asInt(); + if (config.ipVersion != 4 && config.ipVersion != 6) + throw std::runtime_error("Invalid IP Version."); + + config.IP = config.configJsonRoot["IP"].asCString(); + + config.Port = config.configJsonRoot["Port"].asInt(); + if (config.Port < 0 || config.Port > 65535) + throw std::runtime_error("Invalid listen port."); + + int ll_ = config.configJsonRoot["LogLevel"].asInt(); + if (ll_ >= 0 && ll_ < spdlog::level::n_levels) + config.logLevel = (spdlog::level::level_enum)ll_; + else + throw std::runtime_error("Invalid log level."); + + config.logFileName = config.configJsonRoot["LogfileName"].asCString(); + config.logfileSize = config.configJsonRoot["LogfileSize"].asUInt(); + config.logfileCount = config.configJsonRoot["LogfileCount"].asUInt(); + } + catch (Json::RuntimeError e) { + spdlog::critical(std::string(std::string("[Json Error: ]") + e.what()).c_str()); + std::exit(EXIT_FAILURE); + } + return config; +} +} \ No newline at end of file diff --git a/Client/src/client.cpp b/Client/src/client.cpp index afd5ae6..5a15b63 100644 --- a/Client/src/client.cpp +++ b/Client/src/client.cpp @@ -1,11 +1,17 @@ +#define _CLIENT #include "Socket/TCPSocket.hpp" #include "Socket/Address.hpp" #include "Socket/Log.hpp" #include "Packet/Packet.hpp" #include "Utils/Snowflake.hpp" +#include "ClientManager/ClientManager.hpp" #include "precomp.hpp" int main() { + Chattr::ClientManager client; + client.init(); + client.run(); + Chattr::TCPSocket sock; sock.init(AF_INET6); diff --git a/Server/include/ServerManager/ServerManager.hpp b/Server/include/ServerManager/ServerManager.hpp index b10ba04..0ef0e93 100644 --- a/Server/include/ServerManager/ServerManager.hpp +++ b/Server/include/ServerManager/ServerManager.hpp @@ -16,27 +16,29 @@ public: void init(_Callable _IOCPClient) { auto config = ConfigManager::load(); log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount); - threadPool_.init(2); + threadPool_.init(0); iocp_.init(&threadPool_, _IOCPClient); struct Address serveraddr; if (config.ipVersion == 4) { listenSock_.init(AF_INET); - serveraddr.set(AF_INET, INADDR_ANY, config.listenPort); + serveraddr.set(AF_INET, config.IP, config.Port); clientAddr_.setType(AF_INET); } else if (config.ipVersion == 6) { listenSock_.init(AF_INET6); - serveraddr.set(AF_INET6, in6addr_any, config.listenPort); + serveraddr.set(AF_INET6, config.IP, config.Port); clientAddr_.setType(AF_INET6); } listenSock_.bind(serveraddr); listenSock_.listen(SOMAXCONN); + + spdlog::info("Server listening on [{}]", (std::string)serveraddr); } void init() { init([this](ThreadPool* thread, IOCPPASSINDATA* data) { - _IOCPClient(thread, data); + this->_IOCPClient(thread, data); }); } @@ -53,7 +55,7 @@ public: void deleteUser(Snowflake UID); std::vector> getUserList(); - void createRoom(std::string roomName); + Snowflake createRoom(std::string roomName); void deleteRoom(Snowflake RID); std::vector> getRoomList(); diff --git a/Server/src/ServerManager/ServerManager.cpp b/Server/src/ServerManager/ServerManager.cpp index 19dc5e5..ea9f8aa 100644 --- a/Server/src/ServerManager/ServerManager.cpp +++ b/Server/src/ServerManager/ServerManager.cpp @@ -175,7 +175,7 @@ void ServerManager::processLoginRequestPacket(LoginRequestPacket loginRequestPac LoginResponsePacket loginResponsePacket; loginResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; loginResponsePacket.__data.requestType = Chattr::RequestType::LOGIN; - loginResponsePacket.__data.dataType = Chattr::DataType::TEXT; + loginResponsePacket.__data.dataType = Chattr::DataType::BINARY; loginResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(Snowflake); loginResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; Snowflake yourId = userSocket2UID_[data->socket]; @@ -189,15 +189,101 @@ void ServerManager::processLoginRequestPacket(LoginRequestPacket loginRequestPac } void ServerManager::processRoomCreateRequestPacket(RoomCreateRequestPacket roomCreateRequestPacket, Chattr::IOCPPASSINDATA* data) { + std::string roomName( + (char*)roomCreateRequestPacket.__data.data, + roomCreateRequestPacket.__data.packetLength); + Snowflake RID = createRoom(roomName); + + RoomCreateResponsePacket roomCreateResponsePacket; + roomCreateResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + roomCreateResponsePacket.__data.requestType = Chattr::RequestType::ROOM_CREATE; + roomCreateResponsePacket.__data.dataType = Chattr::DataType::BINARY; + roomCreateResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(Snowflake); + roomCreateResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + ::memcpy(roomCreateResponsePacket.__data.createdRoomId, &RID, sizeof(Snowflake)); + + roomCreateResponsePacket.convToN(); + memcpy(data->wsabuf.buf, roomCreateResponsePacket.serialized, 18); + data->sendbytes = 18; + data->wsabuf.len = 18; + data->IOCPInstance->send(data, 1, 0); } void ServerManager::processRoomListRequest(RoomListRequestPacket roomListRequestPacket, Chattr::IOCPPASSINDATA* data) { + auto roomsList = getRoomList(); + + for (auto room : roomsList) { + RoomListResponsePacket roomListResponsePacket; + roomListResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + roomListResponsePacket.__data.requestType = Chattr::RequestType::ROOM_LIST; + roomListResponsePacket.__data.dataType = Chattr::DataType::BINARY; + roomListResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode) + sizeof(std::uint32_t) + sizeof(Snowflake) + room.second.size(); + roomListResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + roomListResponsePacket.__data.roomCount = roomsList.size(); + ::memcpy(roomListResponsePacket.__data.roomId, &room.first, sizeof(Snowflake)); + ::memcpy(roomListResponsePacket.__data.name, room.second.c_str(), room.second.size()); + + int packetLength = roomListResponsePacket.__data.packetLength; + + Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + ptr->socket = data->socket; + ptr->recvbytes = ptr->sendbytes = 0; + ptr->wsabuf.buf = ptr->buf; + ptr->wsabuf.len = packetLength + 8; + ptr->IOCPInstance = data->IOCPInstance; + + roomListResponsePacket.convToN(); + memcpy(ptr->wsabuf.buf, roomListResponsePacket.serialized, packetLength + 8); + data->sendbytes = packetLength + 8; + data->IOCPInstance->send(ptr, 1, 0); + } } void ServerManager::processRoomJoinRequestPacket(RoomJoinRequestPacket roomJoinRequestPacket, Chattr::IOCPPASSINDATA* data) { + Snowflake myID, roomID; + ::memcpy(&myID.snowflake, roomJoinRequestPacket.__data.myId, sizeof(Snowflake)); + ::memcpy(&roomID.snowflake, roomJoinRequestPacket.__data.roomId, sizeof(Snowflake)); + + joinRoom(myID, roomID); + + RoomJoinResponsePacket roomJoinResponsePacket; + roomJoinResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + roomJoinResponsePacket.__data.requestType = Chattr::RequestType::ROOM_JOIN; + roomJoinResponsePacket.__data.dataType = Chattr::DataType::BINARY; + roomJoinResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + roomJoinResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + int packetLength = roomJoinResponsePacket.__data.packetLength; + + roomJoinResponsePacket.convToN(); + ::memcpy(data->wsabuf.buf, roomJoinResponsePacket.serialized, 10); + data->sendbytes = 10; + data->wsabuf.len = 10; + data->IOCPInstance->send(data, 1, 0); } void ServerManager::processRoomExitRequestPacket(RoomExitRequestPacket roomExitRequestPacket, Chattr::IOCPPASSINDATA* data) { + Snowflake myID, roomID; + ::memcpy(&myID.snowflake, roomExitRequestPacket.__data.myId, sizeof(Snowflake)); + ::memcpy(&roomID.snowflake, roomExitRequestPacket.__data.roomId, sizeof(Snowflake)); + + exitRoom(myID, roomID); + + RoomExitResponsePacket roomExitResponsePacket; + roomExitResponsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + roomExitResponsePacket.__data.requestType = Chattr::RequestType::ROOM_EXIT; + roomExitResponsePacket.__data.dataType = Chattr::DataType::BINARY; + roomExitResponsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + roomExitResponsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + int packetLength = roomExitResponsePacket.__data.packetLength; + + roomExitResponsePacket.convToN(); + ::memcpy(data->wsabuf.buf, roomExitResponsePacket.serialized, 10); + data->sendbytes = 10; + data->wsabuf.len = 10; + data->IOCPInstance->send(data, 1, 0); } void ServerManager::processUsersListRequestPacket(UsersListRequestPacket usersListRequestPacket, Chattr::IOCPPASSINDATA* data) { @@ -281,6 +367,51 @@ void ServerManager::processDataPostPacket(DataPostPacket dataPostPacket, IOCPPAS } void ServerManager::processContinuePacket(ContinuePacket continuePacket, IOCPPASSINDATA* data) { + Snowflake destID; + ::memcpy(&destID.snowflake, continuePacket.__data.destId, sizeof(Snowflake)); + + std::vector> destinationSockets; + + if (userNames_.find(destID) != userNames_.end()) + destinationSockets.push_back(UID2userSocket_[destID]); + else + for (auto user : rooms_[destID]) + destinationSockets.push_back(user.second); + + spdlog::info("Received [{}] from : [{}] to : [{}]", + std::string((char*)continuePacket.__data.data, continuePacket.__data.packetLength - (sizeof(std::uint16_t) * 5)), + (std::string)data->socket->remoteAddr, + destID.snowflake); + + ResponsePacket responsePacket; + responsePacket.__data.packetType = Chattr::PacketCategory::PACKET_RESPONSE; + responsePacket.__data.requestType = Chattr::RequestType::DATA; + responsePacket.__data.dataType = Chattr::DataType::TEXT; + responsePacket.__data.packetLength = sizeof(Chattr::ResponseStatusCode); + responsePacket.__data.responseStatusCode = Chattr::ResponseStatusCode::OK; + + responsePacket.convToN(); + memcpy(data->wsabuf.buf, responsePacket.serialized, 10); + data->sendbytes = 10; + data->wsabuf.len = 10; + data->IOCPInstance->send(data, 1, 0); + + int packetLength = continuePacket.__data.packetLength; + + for (auto dest : destinationSockets) { + Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; + ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); + ptr->socket = dest; + ptr->recvbytes = ptr->sendbytes = 0; + ptr->wsabuf.buf = ptr->buf; + ptr->wsabuf.len = packetLength + 6; + ptr->IOCPInstance = data->IOCPInstance; + + continuePacket.convToN(); + memcpy(ptr->wsabuf.buf, continuePacket.serialized, packetLength + 6); + data->sendbytes = packetLength + 6; + data->IOCPInstance->send(ptr, 1, 0); + } } void ServerManager::registerUser(std::string userName, std::shared_ptr sock) { @@ -310,11 +441,12 @@ std::vector> ServerManager::getUserList() { return userList; } -void ServerManager::createRoom(std::string roomName) { +Snowflake ServerManager::createRoom(std::string roomName) { std::lock_guard lock(resourceMutex_); Snowflake RID = GenerateID(); roomNames_[RID] = roomName; rooms_[RID] = std::unordered_map>(); + return RID; } void ServerManager::deleteRoom(Snowflake RID) { diff --git a/Server/src/Socket/Log.cpp b/Server/src/Socket/Log.cpp new file mode 100644 index 0000000..6f67a53 --- /dev/null +++ b/Server/src/Socket/Log.cpp @@ -0,0 +1,25 @@ +#include "Socket/Log.hpp" + +#include "spdlog/sinks/stdout_color_sinks.h" +#include "spdlog/sinks/rotating_file_sink.h" +#ifdef _WIN32 +#include "spdlog/sinks/msvc_sink.h" +#endif + +#include "precomp.hpp" + +namespace Chattr::log { + +void setDefaultLogger(spdlog::level::level_enum logLevel, gsl::czstring logFileName, std::uint32_t logFileSize, std::uint32_t logFileCount) { + std::vector sinks; + sinks.push_back(std::make_shared()); + sinks.push_back(std::make_shared(logFileName, logFileSize, logFileCount, false)); +#ifdef _WIN32 + sinks.push_back(std::make_shared()); +#endif + auto chatteringLogger = std::make_shared("Chattering Logger", begin(sinks), end(sinks)); + chatteringLogger->set_level(logLevel); + spdlog::set_default_logger(chatteringLogger); +} + +} \ No newline at end of file diff --git a/Server/src/Utils/ConfigManager.cpp b/Server/src/Utils/ConfigManager.cpp index 1e1c8e0..f668494 100644 --- a/Server/src/Utils/ConfigManager.cpp +++ b/Server/src/Utils/ConfigManager.cpp @@ -13,7 +13,8 @@ ConfigManager::Config ConfigManager::load() { if (!configfile.is_open()) { std::ofstream defaultConfig("config.json", std::ios::out); config.configJsonRoot["IP Version"] = 6; - config.configJsonRoot["Listen Port"] = 9010; + config.configJsonRoot["IP"] = "::"; + config.configJsonRoot["Port"] = 9010; config.configJsonRoot["LogLevel"] = 1; config.configJsonRoot["LogfileName"] = "Chattering.log"; config.configJsonRoot["LogfileSize"] = UINT32_MAX; @@ -30,8 +31,10 @@ ConfigManager::Config ConfigManager::load() { if (config.ipVersion != 4 && config.ipVersion != 6) throw std::runtime_error("Invalid IP Version."); - config.listenPort = config.configJsonRoot["Listen Port"].asInt(); - if (config.listenPort < 0 || config.listenPort > 65535) + config.IP = config.configJsonRoot["IP"].asCString(); + + config.Port = config.configJsonRoot["Port"].asInt(); + if (config.Port < 0 || config.Port > 65535) throw std::runtime_error("Invalid listen port."); int ll_ = config.configJsonRoot["LogLevel"].asInt(); diff --git a/impl/Socket/IOCP.cpp b/impl/Socket/IOCP.cpp index c8634d0..f45e38c 100644 --- a/impl/Socket/IOCP.cpp +++ b/impl/Socket/IOCP.cpp @@ -19,18 +19,18 @@ void IOCP::destruct() { #endif } -void IOCP::registerSocket(Chattr::IOCPPASSINDATA* data) { +void IOCP::registerSocket(IOCPPASSINDATA* data) { #ifdef _WIN32 HANDLE returnData = ::CreateIoCompletionPort((HANDLE)data->socket->sock, completionPort_, data->socket->sock, 0); if (returnData == 0) completionPort_ = returnData; #elif __linux__ - int flags = ::fcntl(data->socket->sock, F_GETFL); - flags |= O_NONBLOCK; - fcntl(data->socket->sock, F_SETFL, flags); + // int flags = ::fcntl(data->socket->sock, F_GETFL); + // flags |= O_NONBLOCK; + // fcntl(data->socket->sock, F_SETFL, flags); struct epoll_event ev; - ev.events = EPOLLIN | EPOLLONESHOT; + ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT; ev.data.ptr = data; int rc = epoll_ctl(epollfd_, EPOLL_CTL_ADD, data->socket->sock, &ev); if (rc < 0) @@ -45,20 +45,23 @@ int IOCP::recv(Chattr::IOCPPASSINDATA* data, int bufferCount) { return ::WSARecv(data->socket->sock, &data->wsabuf, bufferCount, &recvbytes, &flags, &data->overlapped, NULL); #elif __linux__ struct epoll_event ev; - ev.events = EPOLLIN | EPOLLONESHOT; + ev.events = EPOLLIN | EPOLLET | EPOLLONESHOT; ev.data.ptr = data; return ::epoll_ctl(epollfd_, EPOLL_CTL_MOD, data->socket->sock, &ev); #endif } -int IOCP::send(Chattr::IOCPPASSINDATA* data, int bufferCount, int __flags) { +int IOCP::send(Chattr::IOCPPASSINDATA* data, int bufferCount, int __flags, bool client) { data->event = IOCPEVENT::WRITE; #ifdef _WIN32 DWORD sendbytes = 0; return ::WSASend(data->socket->sock, &data->wsabuf, bufferCount, &sendbytes, __flags, &data->overlapped, NULL); #elif __linux__ struct epoll_event ev; - ev.events = EPOLLOUT | EPOLLONESHOT; + if (client) + ev.events = EPOLLIN | EPOLLOUT | EPOLLET | EPOLLONESHOT; + else + ev.events = EPOLLOUT | EPOLLET | EPOLLONESHOT; ev.data.ptr = data; return ::epoll_ctl(epollfd_, EPOLL_CTL_MOD, data->socket->sock, &ev); #endif diff --git a/impl/Socket/Log.cpp b/impl/Socket/Log.cpp index c8d8408..fab5a64 100644 --- a/impl/Socket/Log.cpp +++ b/impl/Socket/Log.cpp @@ -10,18 +10,6 @@ namespace Chattr::log { -void setDefaultLogger(spdlog::level::level_enum logLevel, gsl::czstring logFileName, std::uint32_t logFileSize, std::uint32_t logFileCount) { - std::vector sinks; - sinks.push_back(std::make_shared()); - sinks.push_back(std::make_shared(logFileName, logFileSize, logFileCount, false)); -#ifdef _WIN32 - sinks.push_back(std::make_shared()); -#endif - auto chatteringLogger = std::make_shared("Chattering Logger", begin(sinks), end(sinks)); - chatteringLogger->set_level(logLevel); - spdlog::set_default_logger(chatteringLogger); -} - void critical(gsl::czstring msg) { #ifdef _WIN32 LPSTR msgbuf = nullptr; diff --git a/include/Packet/Packet.hpp b/include/Packet/Packet.hpp index e517fad..4dca98f 100644 --- a/include/Packet/Packet.hpp +++ b/include/Packet/Packet.hpp @@ -84,26 +84,61 @@ public: RequestType requestType; DataType dataType; std::uint16_t packetLength; - std::uint16_t destId[4]; + std::uint16_t myId[4]; + std::uint16_t roomId[4]; std::uint8_t name[]; } __data; std::uint8_t serialized[1500] = ""; }; std::uint8_t* convToN() { __data.packetLength = ::htons(__data.packetLength); - for (int i = 0; i < 4; i++) - __data.destId[i] = ::htons(__data.destId[i]); + for (int i = 0; i < 4; i++) { + __data.myId[i] = ::htons(__data.myId[i]); + __data.roomId[i] = ::htons(__data.roomId[i]); + } return serialized; } std::uint8_t* convToH() { __data.packetLength = ::ntohs(__data.packetLength); - for (int i = 0; i < 4; i++) - __data.destId[i] = ::ntohs(__data.destId[i]); + for (int i = 0; i < 4; i++) { + __data.myId[i] = ::ntohs(__data.myId[i]); + __data.roomId[i] = ::ntohs(__data.roomId[i]); + } return serialized; } }; -class alignas(4) RoomExitRequestPacket : public Packet {}; +class alignas(4) RoomExitRequestPacket : public Packet { +public: + union { + struct { + PacketCategory packetType; + RequestType requestType; + DataType dataType; + std::uint16_t packetLength; + std::uint16_t myId[4]; + std::uint16_t roomId[4]; + std::uint8_t name[]; + } __data; + std::uint8_t serialized[1500] = ""; + }; + std::uint8_t* convToN() { + __data.packetLength = ::htons(__data.packetLength); + for (int i = 0; i < 4; i++) { + __data.myId[i] = ::htons(__data.myId[i]); + __data.roomId[i] = ::htons(__data.roomId[i]); + } + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + for (int i = 0; i < 4; i++) { + __data.myId[i] = ::ntohs(__data.myId[i]); + __data.roomId[i] = ::ntohs(__data.roomId[i]); + } + return serialized; + } +}; class alignas(4) UsersListRequestPacket : public Packet {}; diff --git a/include/Socket/IOCP.hpp b/include/Socket/IOCP.hpp index 892e9f0..38b6337 100644 --- a/include/Socket/IOCP.hpp +++ b/include/Socket/IOCP.hpp @@ -226,7 +226,7 @@ public: void registerSocket(IOCPPASSINDATA* data); int recv(IOCPPASSINDATA* data, int bufferCount); - int send(IOCPPASSINDATA* data, int bufferCount, int __flags); + int send(IOCPPASSINDATA* data, int bufferCount, int __flags, bool client = false); private: struct WSAManager wsaManager; diff --git a/include/Utils/ConfigManager.hpp b/include/Utils/ConfigManager.hpp index d0c6e2a..77f573d 100644 --- a/include/Utils/ConfigManager.hpp +++ b/include/Utils/ConfigManager.hpp @@ -7,7 +7,8 @@ public: struct Config { Json::Value configJsonRoot; std::uint32_t ipVersion = 0; - std::uint32_t listenPort = 0; + gsl::czstring IP = ""; + std::uint32_t Port = 0; spdlog::level::level_enum logLevel = spdlog::level::off; gsl::czstring logFileName = ""; std::uint32_t logfileSize = 0;