일단 이제 자잘한 버그만 고치면 될 듯?

This commit is contained in:
2025-05-04 14:31:30 +09:00
parent 63428ebf4d
commit e0a371d536
16 changed files with 908 additions and 39 deletions

View File

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

View File

@@ -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<typename _Callable>
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<TCPSocket>(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<std::pair<Snowflake, std::string>> getUserList();
Snowflake createRoom(std::string roomName);
void deleteRoom(Snowflake RID);
std::vector<std::pair<Snowflake, std::string>> 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<Snowflake, std::string> roomNames_;
std::unordered_map<Snowflake, std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>>> rooms_;
std::unordered_map<Snowflake, std::shared_ptr<TCPSocket>> UID2userSocket_;
std::unordered_map<std::shared_ptr<TCPSocket>, Snowflake> userSocket2UID_;
std::unordered_map<Snowflake, std::string> userNames_;
};
}

View File

@@ -0,0 +1,488 @@
#include "ClientManager/ClientManager.hpp"
#include "Utils/ConfigManager.hpp"
#include "Utils/StringTokenizer.hpp"
#include "Socket/Log.hpp"
#include <iostream>
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<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 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<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*)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<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>> ClientManager::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;
}
Snowflake ClientManager::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>>();
return RID;
}
void ClientManager::deleteRoom(Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
roomNames_.erase(RID);
rooms_.erase(RID);
}
std::vector<std::pair<Snowflake, std::string>> ClientManager::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 ClientManager::joinRoom(Snowflake UID, Snowflake RID) {
std::lock_guard<std::mutex> lock(resourceMutex_);
std::shared_ptr<TCPSocket> sock = UID2userSocket_[UID];
rooms_[RID][UID] = sock;
}
void ClientManager::exitRoom(Snowflake UID, Snowflake RID) {
std::lock_guard<std::mutex> 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 <username> : Send direct message to specified user" << std::endl;
std::cout << "/join <roomname> : Enter specified room" << std::endl;
std::cout << "/exit : Exit current room" << std::endl;
std::cout << "/create <roomname> : 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());
}
}
}

25
Client/src/Socket/Log.cpp Normal file
View File

@@ -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<spdlog::sink_ptr> sinks;
sinks.push_back(std::make_shared<spdlog::sinks::stdout_color_sink_mt>());
sinks.push_back(std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logFileName, logFileSize, logFileCount, false));
#ifdef _WIN32
sinks.push_back(std::make_shared<spdlog::sinks::msvc_sink_mt>());
#endif
auto chatteringLogger = std::make_shared<spdlog::logger>("Chattering Logger", begin(sinks), end(sinks));
chatteringLogger->set_level(logLevel);
spdlog::set_default_logger(chatteringLogger);
}
}

View File

@@ -0,0 +1,56 @@
#include "Utils/ConfigManager.hpp"
#include "precomp.hpp"
#include <fstream>
#include <json/json.h>
#include <iostream>
#include <string>
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;
}
}

View File

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