#include "ServerManager/ServerManager.hpp" #include "Utils/ConfigManager.hpp" #include "Socket/Log.hpp" namespace Chattr { void ServerManager::_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::LOGINREQUEST: { LoginRequestPacket loginRequestPacket; std::memcpy(&loginRequestPacket.serialized, pack.serialized, 8 + packetLength); loginRequestPacket.convToH(); processLoginRequestPacket(loginRequestPacket, data); } break; case PacketSet::ROOMCREATEREQUEST: { RoomCreateRequestPacket roomCreateRequestPacket; std::memcpy(&roomCreateRequestPacket.serialized, pack.serialized, 8 + packetLength); roomCreateRequestPacket.convToH(); processRoomCreateRequestPacket(roomCreateRequestPacket, data); } break; case PacketSet::ROOMLISTREQUEST: { RoomListRequestPacket roomListRequestPacket; std::memcpy(&roomListRequestPacket.serialized, pack.serialized, 8 + packetLength); roomListRequestPacket.convToH(); processRoomListRequest(roomListRequestPacket, data); } break; case PacketSet::ROOMJOINREQUEST: { RoomJoinRequestPacket roomJoinRequestPacket; std::memcpy(&roomJoinRequestPacket.serialized, pack.serialized, 8 + packetLength); roomJoinRequestPacket.convToH(); processRoomJoinRequestPacket(roomJoinRequestPacket, data); } break; case PacketSet::ROOMEXITREQUEST: { RoomExitRequestPacket roomExitRequestPacket; std::memcpy(&roomExitRequestPacket.serialized, pack.serialized, 8 + packetLength); roomExitRequestPacket.convToH(); processRoomExitRequestPacket(roomExitRequestPacket, data); } break; case PacketSet::USERSLISTREQUEST: { UsersListRequestPacket usersListRequestPacket; std::memcpy(&usersListRequestPacket.serialized, pack.serialized, 8 + packetLength); usersListRequestPacket.convToH(); processUsersListRequestPacket(usersListRequestPacket, 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: { 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::BAD_REQUEST; responsePacket.convToN(); memcpy(data->wsabuf.buf, responsePacket.serialized, 10); data->sendbytes = 10; data->wsabuf.len = 10; data->IOCPInstance->send(data, 1, 0); } break; } } PacketSet ServerManager::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::INVALID; } break; case PacketCategory::PACKET_CONTINUE: return PacketSet::CONTINUE; default: return PacketSet::INVALID; } return PacketSet::INVALID; } void ServerManager::processLoginRequestPacket(LoginRequestPacket loginRequestPacket, Chattr::IOCPPASSINDATA* data) { std::string userName( (char*)loginRequestPacket.__data.data, loginRequestPacket.__data.packetLength); registerUser(userName, data->socket); 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::RES_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 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::RES_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::RES_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::RES_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::RES_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) { 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::RES_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 ServerManager::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::RES_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 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::RES_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) { std::lock_guard lock(resourceMutex_); Snowflake UID = GenerateID(); userNames_[UID] = userName; UID2userSocket_[UID] = sock; userSocket2UID_[sock] = UID; } void ServerManager::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> ServerManager::getUserList() { std::lock_guard lock(resourceMutex_); std::vector> userList; userList.reserve(userNames_.size()); for (auto user : userNames_) userList.push_back(user); return userList; } 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) { std::lock_guard lock(resourceMutex_); roomNames_.erase(RID); rooms_.erase(RID); } std::vector> ServerManager::getRoomList() { std::lock_guard lock(resourceMutex_); std::vector> roomList; roomList.reserve(roomNames_.size()); for (auto user : roomNames_) roomList.push_back(user); return roomList; } void ServerManager::joinRoom(Snowflake UID, Snowflake RID) { std::lock_guard lock(resourceMutex_); std::shared_ptr sock = UID2userSocket_[UID]; rooms_[RID][UID] = sock; } void ServerManager::exitRoom(Snowflake UID, Snowflake RID) { std::lock_guard lock(resourceMutex_); rooms_[RID].erase(UID); } void ServerManager::run() { while (true) { spdlog::info("Waiting for connection..."); listenSock_.accept(clientSock_, clientAddr_); bool enable = true; clientSock_.setsockopt(SOL_SOCKET, SO_KEEPALIVE, (const char*)&enable, sizeof(enable)); Chattr::IOCPPASSINDATA* ptr = new Chattr::IOCPPASSINDATA; ::memset(&ptr->overlapped, 0, sizeof(OVERLAPPED)); ptr->socket = std::make_shared(std::move(clientSock_)); ptr->recvbytes = ptr->sendbytes = 0; ptr->wsabuf.buf = ptr->buf; ptr->wsabuf.len = 1500; ptr->IOCPInstance = &iocp_; iocp_.registerSocket(ptr); int returnData = iocp_.recv(ptr, 1); } } }