Files
NP_Midterm/Server/src/ServerManager/ServerManager.cpp
2025-05-03 18:55:13 +09:00

328 lines
12 KiB
C++

#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->recvbytes == 0) {
data->recvbytes = data->transferredbytes;
data->transferredbytes = 0;
}
else if (data->transferredbytes <= data->sendbytes) {
data->IOCPInstance->recv(data, 1);
return;
}
memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len);
DataPostPacket dataPostPacket;
ResponsePacket responsePacket;
pack.convToH();
std::uint16_t packetLength = pack.__data.packetLength;
switch (packetParser(pack)) {
case PacketSet::LOGINREQUEST: {
pack.convToN();
LoginRequestPacket loginRequestPacket;
std::memcpy(&loginRequestPacket.serialized, &pack, 8 + packetLength);
loginRequestPacket.convToH();
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::TEXT;
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, 16);
data->sendbytes = 16;
data->transferredbytes = 16;
data->wsabuf.len = 16;
data->IOCPInstance->send(data, 1, 0);
}
break;
case PacketSet::ROOMCREATEREQUEST:
break;
case PacketSet::ROOMLISTREQUEST:
break;
case PacketSet::ROOMJOINREQUEST:
break;
case PacketSet::ROOMEXITREQUEST:
break;
case PacketSet::USERSLISTREQUEST: {
pack.convToN();
UsersListRequestPacket usersListRequestPacket;
std::memcpy(&usersListRequestPacket.serialized, &pack, 8 + packetLength);
usersListRequestPacket.convToH();
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 sendPacketLength = 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 = 1500;
ptr->IOCPInstance = data->IOCPInstance;
usersListResponsePacket.convToN();
memcpy(ptr->wsabuf.buf, usersListResponsePacket.serialized, sendPacketLength + 8);
data->sendbytes = sendPacketLength + 8;
data->transferredbytes = sendPacketLength + 8;
data->wsabuf.len = sendPacketLength + 8;
data->IOCPInstance->send(ptr, 1, 0);
}
}
break;
case PacketSet::DATAPOSTTEXT: {
pack.convToN();
std::memcpy(&dataPostPacket.serialized, &pack, 8 + packetLength);
dataPostPacket.convToH();
Snowflake destID = {};
::memcpy(&destID.snowflake, dataPostPacket.__data.destId, sizeof(Snowflake));
std::vector<std::shared_ptr<TCPSocket>> 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.__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->transferredbytes = 10;
data->wsabuf.len = 10;
data->IOCPInstance->send(data, 1, 0);
for (auto dest : destinationSockets) {
dataPostPacket.__data.packetType = Chattr::PacketCategory::PACKET_POST;
dataPostPacket.__data.requestType = Chattr::RequestType::DATA;
dataPostPacket.__data.dataType = Chattr::DataType::TEXT;
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 = 1500;
ptr->IOCPInstance = data->IOCPInstance;
dataPostPacket.convToN();
memcpy(ptr->wsabuf.buf, dataPostPacket.serialized, packetLength + 6);
data->sendbytes = packetLength + 6;
data->transferredbytes = packetLength + 6;
data->wsabuf.len = packetLength + 6;
data->IOCPInstance->send(ptr, 1, 0);
}
}
break;
case PacketSet::DATAPOSTBINARY:
break;
case PacketSet::CONTINUE:
break;
case PacketSet::INVALID:
default:
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->transferredbytes = 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:
return PacketSet::DATAPOSTTEXT;
case DataType::BINARY:
return PacketSet::DATAPOSTBINARY;
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::registerUser(std::string userName, std::shared_ptr<TCPSocket> sock) {
std::lock_guard<std::mutex> lock(resourceMutex_);
Snowflake UID = GenerateID();
userNames_[UID] = userName;
UID2userSocket_[UID] = sock;
userSocket2UID_[sock] = UID;
}
void ServerManager::deleteUser(Snowflake UID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
userNames_.erase(UID);
std::shared_ptr<TCPSocket> sock = UID2userSocket_[UID];
UID2userSocket_.erase(UID);
userSocket2UID_.erase(sock);
}
std::vector<std::pair<Snowflake, std::string>> ServerManager::getUserList() {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::vector<std::pair<Snowflake, std::string>> userList;
userList.reserve(userNames_.size());
for (auto user : userNames_)
userList.push_back(user);
return userList;
}
void ServerManager::createRoom(std::string roomName) {
std::lock_guard<std::mutex> lock(resourceMutex_);
Snowflake RID = GenerateID();
roomNames_[RID] = roomName;
rooms_[RID] = std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>>();
}
void ServerManager::deleteRoom(Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
roomNames_.erase(RID);
rooms_.erase(RID);
}
std::vector<std::pair<Snowflake, std::string>> ServerManager::getRoomList() {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::vector<std::pair<Snowflake, std::string>> 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<std::mutex> lock(resourceMutex_);
std::shared_ptr<TCPSocket> sock = UID2userSocket_[UID];
rooms_[RID][UID] = sock;
}
void ServerManager::exitRoom(Snowflake UID, Snowflake RID) {
std::lock_guard<std::mutex> 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<TCPSocket>(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);
}
}
}