diff --git a/Client/src/client.cpp b/Client/src/client.cpp index 261b103..ca6d0fa 100644 --- a/Client/src/client.cpp +++ b/Client/src/client.cpp @@ -14,7 +14,7 @@ int main() { spdlog::info("Connection established from {}", (std::string)serveraddr); Chattr::DataPostPacket dataPostPacket; - dataPostPacket.__data.packetType = Chattr::PacketType::PACKET_POST; + dataPostPacket.__data.packetType = Chattr::PacketCategory::PACKET_POST; dataPostPacket.__data.requestType = Chattr::RequestType::DATA; dataPostPacket.__data.dataType = Chattr::DataType::TEXT; memcpy(dataPostPacket.__data.data, "Hello, World!", 14); diff --git a/Server/include/ServerManager/ServerManager.hpp b/Server/include/ServerManager/ServerManager.hpp index 03ad76e..97b2b74 100644 --- a/Server/include/ServerManager/ServerManager.hpp +++ b/Server/include/ServerManager/ServerManager.hpp @@ -1,11 +1,81 @@ #pragma once +#include "Utils/ThreadPool.hpp" +#include "Utils/ConfigManager.hpp" +#include "Socket/IOCP.hpp" +#include "Packet/Packet.hpp" namespace Chattr { class ServerManager { public: - void init(); - void + 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) { + listenSock_.init(AF_INET); + serveraddr.set(AF_INET, INADDR_ANY, config.listenPort); + clientAddr_.setType(AF_INET); + } + else if (config.ipVersion == 6) { + listenSock_.init(AF_INET6); + serveraddr.set(AF_INET6, in6addr_any, config.listenPort); + clientAddr_.setType(AF_INET6); + } + listenSock_.bind(serveraddr); + listenSock_.listen(SOMAXCONN); + } + + void init() { + init([this](ThreadPool* thread, IOCPPASSINDATA* data) { + _IOCPClient(thread, data); + }); + } + + void registerUser(std::string userName, std::shared_ptr sock); + void deleteUser(Snowflake UID); + std::vector> getUserList(); + + void createRoom(std::string roomName); + void deleteRoom(Snowflake RID); + std::vector> getRoomList(); + + void joinRoom(Snowflake UID, Snowflake RID); + void exitRoom(Snowflake UID, Snowflake RID); + + Snowflake generateID(); + + void run(); +private: + ThreadPool threadPool_; + IOCP iocp_; + + TCPSocket listenSock_; + + TCPSocket clientSock_; + struct Address clientAddr_; + + std::mutex resourceMutex_; + std::mutex snowflakeGenerateMutex_; + + std::unordered_map roomNames_; + + std::unordered_map>> rooms_; + + std::unordered_map> UID2userSocket_; + std::unordered_map userSocket2UID_; + + std::unordered_map userNames_; + + }; } \ No newline at end of file diff --git a/Server/src/ServerManager/ServerManager.cpp b/Server/src/ServerManager/ServerManager.cpp index e69de29..7919fc7 100644 --- a/Server/src/ServerManager/ServerManager.cpp +++ b/Server/src/ServerManager/ServerManager.cpp @@ -0,0 +1,250 @@ +#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->transfrredbytes; + + if (data->recvbytes == 0) { + data->recvbytes = data->transfrredbytes; + data->transfrredbytes = 0; + } + else if (data->transfrredbytes <= data->sendbytes) { + data->IOCPInstance->recv(data, 1); + return; + } + + memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len); + pack.convToH(); + + std::string recvString; + bool packetError = false; + + DataPostPacket dataPostPacket; + ResponsePacket responsePacket; + LoginRequestPacket loginRequestPacket; + + switch (packetParser(pack)) { + case PacketSet::LOGINREQUEST: + break; + case PacketSet::ROOMCREATEREQUEST: + break; + case PacketSet::ROOMLISTREQUEST: + break; + case PacketSet::ROOMJOINREQUEST: + break; + case PacketSet::ROOMEXITREQUEST: + break; + case PacketSet::USERSLISTREQUEST: + break; + case PacketSet::DATAPOSTTEXT: + std::memcpy(&dataPostPacket.serialized, &pack, 1500); + dataPostPacket.__data.packetLength = (dataPostPacket.__data.packetLength > 1487) ? 1487 : dataPostPacket.__data.packetLength; + recvString = std::string((char*)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t) * 4)); + spdlog::info("Received [{}] from : [{}]", recvString, (std::string)data->socket->remoteAddr); + + 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, responsePacket.__data.packetLength + 8); + + // data->sendbytes = responsePacket.__data.packetLength + 5; + data->sendbytes = 1500; + data->IOCPInstance->send(data, 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, responsePacket.__data.packetLength + 8); + // data->sendbytes = responsePacket.__data.packetLength + 5; + data->sendbytes = responsePacket.__data.packetLength + 8; + data->transfrredbytes = responsePacket.__data.packetLength + 8; + data->IOCPInstance->send(data, 1, 0); + break; + } +} + +PacketSet ServerManager::packetParser(Packet Packet) { + if (Packet.__data.packetLength < 0 || Packet.__data.packetLength > 1500) + 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; + } +} + +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.get()] = 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.get()); +} + +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; +} + +void ServerManager::createRoom(std::string roomName) { + std::lock_guard lock(resourceMutex_); + Snowflake RID = generateID(); + roomNames_[RID] = roomName; + rooms_[RID] = std::unordered_map>(); +} + +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); +} + +static struct _EPOCH { + _EPOCH() { + EPOCH = std::chrono::system_clock::now(); + } + std::chrono::system_clock::time_point EPOCH; +} __EPOCH__; + +Snowflake ServerManager::generateID() { + std::lock_guard lock(snowflakeGenerateMutex_); +#ifdef _WIN32 + DWORD tid = GetCurrentThreadId(); +#elif __linux__ + pthread_t tid = pthread_self(); +#endif + static int sequence = 0; + Snowflake id = {}; + + auto timestamp = std::chrono::duration_cast(std::chrono::system_clock::now() - __EPOCH__.EPOCH); + id.timestamp = timestamp.count(); + id.instance = tid; + id.sequence = sequence++; + + return id; +} + +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); + } +} + +} \ No newline at end of file diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 2fcf01a..994aa25 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -1,194 +1,9 @@ -#include "Socket/TCPSocket.hpp" -#include "Socket/Log.hpp" -#include "Socket/WSAManager.hpp" -#include "Utils/ConfigManager.hpp" -#include "Utils/Thread.hpp" -#include "Utils/ThreadPool.hpp" -#include "Utils/StringTokenizer.hpp" -#include "Utils/Snowflake.hpp" -#include "Socket/IOCP.hpp" -#include "Packet/Packet.hpp" - -#include -#include +#include "ServerManager/ServerManager.hpp" #include "precomp.hpp" -void _IOCPClient(Chattr::ThreadPool* threadPool, Chattr::IOCPPASSINDATA* data); -void _TCPSendClient(Chattr::ThreadPool* threadPool, Chattr::TCPSocket sock, std::queue packets); - int main() { - auto config = Chattr::ConfigManager::load(); - Chattr::log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount); - Chattr::ThreadPool threadPool(0); - Chattr::IOCP iocp; - iocp.init(&threadPool, _IOCPClient); - - Chattr::TCPSocket sock; - struct Chattr::Address serveraddr; - Chattr::TCPSocket clientSock; - struct Chattr::Address clientAddr; - if (config.ipVersion == 4) { - sock.init(AF_INET); - serveraddr.set(AF_INET, INADDR_ANY, config.listenPort); - clientAddr.setType(AF_INET); - } - else if (config.ipVersion == 6) { - sock.init(AF_INET6); - serveraddr.set(AF_INET6, in6addr_any, config.listenPort); - clientAddr.setType(AF_INET6); - } - sock.bind(serveraddr); - sock.listen(SOMAXCONN); - -#ifdef _WIN32 - DWORD pid = GetCurrentProcessId(); -#elif __linux__ - pid_t pid = getpid(); -#endif - spdlog::debug("PID : {}", pid); - - while (true) { - spdlog::info("Waiting for connection..."); - sock.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::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); - } -} - -void _IOCPClient(Chattr::ThreadPool* thread, Chattr::IOCPPASSINDATA* data) { - Chattr::Packet pack; - int packetSize = 1500; - int totalRedSize = 0; - int redSize = 0; - - if (data->wsabuf.len == data->sendbytes) - return; - - memcpy(pack.serialized, data->wsabuf.buf, data->wsabuf.len); - - std::string recvString; - bool packetError = false; - Chattr::DataPostPacket dataPostPacket; - - Chattr::ResponsePacket packet; - std::queue responsePackets; - - switch (pack.__data.packetType) { - case Chattr::PacketType::PACKET_POST: - if (pack.__data.requestType != Chattr::RequestType::DATA){ - packetError = true; - break; - } - switch (pack.__data.dataType) { - case Chattr::DataType::TEXT: - std::memcpy(&dataPostPacket.serialized, &pack, 1500); - dataPostPacket.convToH(); - dataPostPacket.__data.packetLength = (dataPostPacket.__data.packetLength > 1487) ? 1487 : dataPostPacket.__data.packetLength; - recvString = std::string((char *)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - (sizeof(std::uint16_t)*4)); - spdlog::info("Red size : {}, {} from : [{}]", data->wsabuf.len, recvString, (std::string)data->socket.remoteAddr); - break; - case Chattr::DataType::BINARY: - break; - default: - packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE; - packet.__data.requestType = Chattr::RequestType::DATA; - packet.__data.dataType = Chattr::DataType::TEXT; - packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode); - packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST; - packet.convToN(); - responsePackets.push(packet); - packetError = true; - break; - } - break; - case Chattr::PacketType::PACKET_REQUEST: - switch (pack.__data.requestType) { - case Chattr::RequestType::LOGIN: - break; - case Chattr::RequestType::ROOM_CREATE: - break; - case Chattr::RequestType::ROOM_LIST: - break; - case Chattr::RequestType::ROOM_JOIN: - break; - case Chattr::RequestType::ROOM_EXIT: - break; - case Chattr::RequestType::USERS_LIST: - break; - default: - packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE; - packet.__data.requestType = Chattr::RequestType::DATA; - packet.__data.dataType = Chattr::DataType::TEXT; - packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode); - packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST; - packet.convToN(); - responsePackets.push(packet); - packetError = true; - break; - } - break; - case Chattr::PacketType::PACKET_CONTINUE: - break; - default: - packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE; - packet.__data.requestType = Chattr::RequestType::DATA; - packet.__data.dataType = Chattr::DataType::TEXT; - packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode); - packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST; - packet.convToN(); - responsePackets.push(packet); - packetError = true; - break; - } - - packet.__data.packetType = Chattr::PacketType::PACKET_RESPONSE; - packet.__data.requestType = Chattr::RequestType::DATA; - packet.__data.dataType = Chattr::DataType::TEXT; - packet.__data.packetLength = sizeof(Chattr::ResponseStatusCode); - packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST; - packet.convToN(); - - memcpy(data->wsabuf.buf, packet.serialized, data->wsabuf.len); - - int returnData = data->IOCPInstance->send(data, 0); - - // int returnData = data->IOCPInstance->recv(data); -} - -void _TCPSendClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, std::queue packets) { - Chattr::ResponsePacket pack = packets.front(); - packets.pop(); - int packetSize = 1500; - int totalSentSize = 0; - int sentSize = 0; - - spdlog::info("Sending to: [{}]", (std::string)sock.remoteAddr); - - while (totalSentSize < packetSize) { - - sentSize = sock.send(&pack.serialized, 1500 - totalSentSize, 0); - - if (sentSize <= 0) { - spdlog::info("Client disconnected. [{}]", (std::string)sock.remoteAddr); - return; - } - totalSentSize += sentSize; - } - - /*if (packets.empty()) - thread->enqueueJob(_TCPRecvClient, std::move(sock)); - else - thread->enqueueJob(_TCPSendClient, std::move(sock), packets);*/ + Chattr::ServerManager server; + server.init(); + server.run(); } \ No newline at end of file diff --git a/impl/Socket/IOCP.cpp b/impl/Socket/IOCP.cpp index 4460fce..c04cf42 100644 --- a/impl/Socket/IOCP.cpp +++ b/impl/Socket/IOCP.cpp @@ -7,7 +7,7 @@ namespace Chattr { void IOCP::registerSocket(Chattr::IOCPPASSINDATA* data) { #ifdef _WIN32 - HANDLE returnData = ::CreateIoCompletionPort((HANDLE)data->socket.sock, completionPort_, data->socket.sock, 0); + HANDLE returnData = ::CreateIoCompletionPort((HANDLE)data->socket->sock, completionPort_, data->socket->sock, 0); if (returnData == 0) completionPort_ = returnData; #elif __linux__ @@ -24,10 +24,10 @@ void IOCP::registerSocket(Chattr::IOCPPASSINDATA* data) { #endif } -int IOCP::recv(Chattr::IOCPPASSINDATA* data) { +int IOCP::recv(Chattr::IOCPPASSINDATA* data, int bufferCount) { #ifdef _WIN32 DWORD recvbytes = 0, flags = 0; - return ::WSARecv(data->socket.sock, &data->wsabuf, 1, &recvbytes, &flags, &data->overlapped, NULL); + return ::WSARecv(data->socket->sock, &data->wsabuf, bufferCount, &recvbytes, &flags, &data->overlapped, NULL); #elif __linux__ struct epoll_event ev; ev.events = EPOLLIN | EPOLLONESHOT; @@ -36,10 +36,10 @@ int IOCP::recv(Chattr::IOCPPASSINDATA* data) { #endif } -int IOCP::send(Chattr::IOCPPASSINDATA* data, int __flags) { +int IOCP::send(Chattr::IOCPPASSINDATA* data, int bufferCount, int __flags) { #ifdef _WIN32 DWORD sendbytes = 0; - return ::WSASend(data->socket.sock, &data->wsabuf, 1, &sendbytes, __flags, &data->overlapped, NULL); + return ::WSASend(data->socket->sock, &data->wsabuf, bufferCount, &sendbytes, __flags, &data->overlapped, NULL); #elif __linux__ struct epoll_event ev; ev.events = EPOLLOUT | EPOLLONESHOT; diff --git a/impl/Socket/Socket.cpp b/impl/Socket/Socket.cpp index 51f8aa5..d7206a0 100644 --- a/impl/Socket/Socket.cpp +++ b/impl/Socket/Socket.cpp @@ -80,12 +80,24 @@ int Socket::sendto(const void *__buf, size_t __n, int __flags, struct Address __ return retVal; } +Socket::Socket(const Socket& other_) { + memcpy(this, &other_, sizeof(Socket)); + valid_ = false; +} + Socket::Socket(Socket &&other_) noexcept { other_.valid_ = false; memcpy(this, &other_, sizeof(Socket)); valid_ = true; } +Socket& Socket::operator=(const Socket& other_) { + memcpy(this, &other_, sizeof(Socket)); + valid_ = false; + + return *this; +} + Socket& Socket::operator=(Socket && other_) noexcept { other_.valid_ = false; memcpy(this, &other_, sizeof(Socket)); diff --git a/include/Packet/Packet.hpp b/include/Packet/Packet.hpp index 00ef9a2..9ba5a61 100644 --- a/include/Packet/Packet.hpp +++ b/include/Packet/Packet.hpp @@ -5,7 +5,27 @@ namespace Chattr { -enum class PacketType : std::uint8_t { +enum class PacketSet { + LOGINREQUEST, + ROOMCREATEREQUEST, + ROOMLISTREQUEST, + ROOMJOINREQUEST, + ROOMEXITREQUEST, + USERSLISTREQUEST, + DATAPOSTTEXT, + DATAPOSTBINARY, + CONTINUE, + RESPONSE, + LOGINRESPONSE, + ROOMCREATERESPONSE, + ROOMLISTRESPONSE, + ROOMJOINRESPONSE, + ROOMEXITRESPONSE, + USERSLISTRESPONSE, + INVALID +}; + +enum class PacketCategory : std::uint8_t { PACKET_POST, PACKET_REQUEST, PACKET_RESPONSE, @@ -22,6 +42,8 @@ enum class RequestType : std::uint8_t { DATA }; +#define MOREFRAG 0b00000001 + enum class DataType : std::uint8_t { TEXT, BINARY @@ -31,7 +53,7 @@ class alignas(4) Packet { public: union { struct { - PacketType packetType; + PacketCategory packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; @@ -49,106 +71,48 @@ public: } }; -class alignas(4) LoginRequestPacket : public Packet { -public: - union { - struct { - PacketType packetType; - RequestType requestType; - DataType dataType; - std::uint16_t packetLength; - std::uint8_t name[]; - } __data; - std::uint8_t serialized[1500] = ""; - }; -}; +class alignas(4) LoginRequestPacket : public Packet {}; -class alignas(4) RoomCreateRequestPacket : public Packet { -public: - union { - struct { - PacketType packetType; - RequestType requestType; - DataType dataType; - std::uint16_t packetLength; - std::uint8_t name[]; - } __data; - std::uint8_t serialized[1500] = ""; - }; -}; +class alignas(4) RoomCreateRequestPacket : public Packet {}; -class alignas(4) RoomListRequestPacket : public Packet { +class alignas(4) RoomListRequestPacket : public Packet {}; + +class alignas(4) RoomJoinRequestPacket : public Packet { public: union { struct { - PacketType packetType; + PacketCategory packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; - std::uint32_t roomCount; + std::uint16_t destId[4]; std::uint8_t name[]; } __data; std::uint8_t serialized[1500] = ""; }; std::uint8_t* convToN() { __data.packetLength = ::htons(__data.packetLength); - __data.roomCount = ::htonl(__data.roomCount); + for (int i = 0; i < 4; i++) + __data.destId[i] = ::htons(__data.destId[i]); return serialized; } std::uint8_t* convToH() { __data.packetLength = ::ntohs(__data.packetLength); - __data.roomCount = ::ntohl(__data.roomCount); + for (int i = 0; i < 4; i++) + __data.destId[i] = ::ntohs(__data.destId[i]); return serialized; } }; -class alignas(4) RoomJoinRequestPacket : public Packet { -public: - union { - struct { - PacketType packetType; - RequestType requestType; - DataType dataType; - std::uint16_t packetLength; - std::uint8_t name[]; - } __data; - std::uint8_t serialized[1500] = ""; - }; -}; +class alignas(4) RoomExitRequestPacket : public Packet {}; -class alignas(4) RoomExitRequestPacket : public Packet { -public: - union { - struct { - PacketType packetType; - RequestType requestType; - DataType dataType; - std::uint16_t packetLength; - std::uint8_t data[]; - } __data; - std::uint8_t serialized[1500] = ""; - }; -}; - -class alignas(4) UsersListRequestPacket : public Packet { -public: - union { - struct { - PacketType packetType; - RequestType requestType; - DataType dataType; - std::uint16_t packetLength; - std::uint8_t name[]; - } __data; - std::uint8_t serialized[1500] = ""; - }; -}; +class alignas(4) UsersListRequestPacket : public Packet {}; class alignas(4) DataPostPacket : public Packet { public: union { struct { - PacketType packetType; + PacketCategory packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; @@ -175,13 +139,27 @@ class alignas(4) ContinuePacket : public Packet { public: union { struct { - PacketType packetType; - std::uint8_t padding[2]; + PacketCategory packetType; + std::uint8_t padding; + DataType dataType; std::uint16_t packetLength; + std::uint16_t destId[4]; std::uint8_t data[]; } __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]); + 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]); + return serialized; + } }; enum class ResponseStatusCode : std::uint16_t { @@ -201,7 +179,7 @@ class alignas(4) ResponsePacket : public Packet { public: union { struct { - PacketType packetType; + PacketCategory packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; @@ -222,29 +200,98 @@ public: } }; -//enum class RequestType : std::uint8_t { -// LOGIN, -// ROOM_CREATE, -// ROOM_LIST, -// ROOM_JOIN, -// ROOM_EXIT, -// USERS_LIST, -// DATA -//}; +class alignas(4) LoginResponsePacket : public ResponsePacket {}; -class alignas(4) LoginResponsePacket : public ResponsePacket { +class alignas(4) RoomCreateResponsePacket : public ResponsePacket { public: union { struct { - PacketType packetType; + PacketCategory packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; ResponseStatusCode responseStatusCode; + std::uint16_t createdRoomId[4]; std::uint8_t data[]; } __data; std::uint8_t serialized[1500] = ""; }; + std::uint8_t* convToN() { + __data.packetLength = ::htons(__data.packetLength); + for (int i = 0; i < 4; i++) + __data.createdRoomId[i] = ::htons(__data.createdRoomId[i]); + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + for (int i = 0; i < 4; i++) + __data.createdRoomId[i] = ::ntohs(__data.createdRoomId[i]); + return serialized; + } +}; + +class alignas(4) RoomListResponsePacket : public ResponsePacket { +public: + union { + struct { + PacketCategory packetType; + RequestType requestType; + DataType dataType; + std::uint16_t packetLength; + ResponseStatusCode responseStatusCode; + std::uint32_t roomCount; + std::uint16_t roomId[4]; + std::uint8_t name[]; + } __data; + std::uint8_t serialized[1500] = ""; + }; + std::uint8_t* convToN() { + __data.packetLength = ::htons(__data.packetLength); + __data.roomCount = ::htonl(__data.roomCount); + for (int i = 0; i < 4; i++) + __data.roomId[i] = ::htons(__data.roomId[i]); + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + __data.roomCount = ::ntohl(__data.roomCount); + for (int i = 0; i < 4; i++) + __data.roomId[i] = ::ntohs(__data.roomId[i]); + return serialized; + } +}; + +class alignas(4) RoomJoinResponsePacket : public ResponsePacket {}; + +class alignas(4) RoomExitResponsePacket : public ResponsePacket {}; + +class alignas(4) UsersListResponsePacket : public ResponsePacket { +public: + union { + struct { + PacketCategory packetType; + RequestType requestType; + DataType dataType; + std::uint16_t packetLength; + ResponseStatusCode responseStatusCode; + std::uint32_t usersCount; + std::uint16_t userId[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.userId[i] = ::htons(__data.userId[i]); + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + for (int i = 0; i < 4; i++) + __data.userId[i] = ::ntohs(__data.userId[i]); + return serialized; + } }; } \ No newline at end of file diff --git a/include/Socket/IOCP.hpp b/include/Socket/IOCP.hpp index 0ae552d..d0dc89a 100644 --- a/include/Socket/IOCP.hpp +++ b/include/Socket/IOCP.hpp @@ -4,6 +4,8 @@ #include "Socket/TCPSocket.hpp" #include "Socket/Log.hpp" #include +#include + #include "precomp.hpp" #ifndef _WIN32 @@ -25,10 +27,11 @@ class IOCP; struct IOCPPASSINDATA { OVERLAPPED overlapped; - TCPSocket socket; + std::shared_ptr socket; char buf[1501]; - int recvbytes; - int sendbytes; + std::uint32_t recvbytes; + std::uint32_t sendbytes; + std::uint32_t transfrredbytes; WSABUF wsabuf; IOCP* IOCPInstance; }; @@ -38,17 +41,18 @@ public: #ifdef _WIN32 static void iocpWather(ThreadPool* threadPool, HANDLE completionPort_, std::function callback) { DWORD tid = GetCurrentThreadId(); - spdlog::debug("Waiting IO to complete on TID: {}.", tid); + spdlog::trace("Waiting IO to complete on TID: {}.", tid); IOCPPASSINDATA* data; SOCKET sock; DWORD cbTransfrred; int retVal = GetQueuedCompletionStatus(completionPort_, &cbTransfrred, (PULONG_PTR)&sock, (LPOVERLAPPED*)&data, INFINITE); if (retVal == 0 || cbTransfrred == 0) { - spdlog::info("Client disconnected. [{}]", (std::string)(data->socket.remoteAddr)); + spdlog::debug("Client disconnected. [{}]", (std::string)(data->socket->remoteAddr)); delete data; threadPool->enqueueJob(iocpWather, completionPort_, callback); return; } + data->transfrredbytes = cbTransfrred; threadPool->enqueueJob(callback, data); threadPool->enqueueJob(iocpWather, completionPort_, callback); }; @@ -63,7 +67,7 @@ public: return; } - spdlog::info("reading on tid: {} [{}]", tid, (std::string)iocpData->socket.remoteAddr); + spdlog::trace("reading on tid: {} [{}]", tid, (std::string)iocpData->socket.remoteAddr); int redSize = 0; int packetSize = iocpData->wsabuf.len; @@ -73,7 +77,7 @@ public: redSize = iocpData->socket.recv(iocpData->buf, packetSize - totalRedSize, 0); if (redSize <= 0) { - spdlog::info("Client disconnected. [{}]", (std::string)iocpData->socket.remoteAddr); + spdlog::debug("Client disconnected. [{}]", (std::string)iocpData->socket.remoteAddr); ::epoll_ctl(epollfd, EPOLL_CTL_DEL, iocpData->socket.sock, NULL); delete iocpData; return; @@ -91,13 +95,13 @@ public: int totalSentSize = 0; int sentSize = 0; - spdlog::info("Sending to: [{}]", (std::string)iocpData->socket.remoteAddr); + spdlog::trace("Sending to: [{}]", (std::string)iocpData->socket.remoteAddr); while (totalSentSize < packetSize) { sentSize = iocpData->socket.send(iocpData->buf, packetSize - totalSentSize, 0); if (sentSize <= 0) { - spdlog::info("Client disconnected. [{}]", (std::string)iocpData->socket.remoteAddr); + spdlog::debug("Client disconnected. [{}]", (std::string)iocpData->socket.remoteAddr); ::epoll_ctl(epollfd, EPOLL_CTL_DEL, iocpData->socket.sock, NULL); delete iocpData; return; @@ -112,7 +116,7 @@ public: struct epoll_event events[FD_SETSIZE]; pthread_t tid = pthread_self(); - spdlog::debug("epoll waiting on {}", tid); + spdlog::trace("epoll waiting on {}", tid); int nready = ::epoll_wait(epollfd, events, FD_SETSIZE, -1); for (int i=0; i +struct hash { + std::size_t operator()(const Chattr::Snowflake& k) const { + return std::hash{}(k.snowflake); + } +}; } \ No newline at end of file diff --git a/include/Utils/Thread.hpp b/include/Utils/Thread.hpp index d76ee94..b0c1466 100644 --- a/include/Utils/Thread.hpp +++ b/include/Utils/Thread.hpp @@ -64,9 +64,9 @@ public: handle_ = (HANDLE)_beginthreadex(nullptr, 0, thread_func, funcPtr, 0, nullptr); #elif __linux__ int rc = pthread_create(&handle_, NULL, thread_func, funcPtr); -#endif if (handle_ <= 0 || rc != 0) log::critical("pthread_create()"); +#endif } ~Thread(); diff --git a/include/precomp.hpp b/include/precomp.hpp index 6259efb..d2c02b2 100644 --- a/include/precomp.hpp +++ b/include/precomp.hpp @@ -24,13 +24,4 @@ #include #include -#include "spdlog/spdlog.h" - -namespace Chattr { -static struct _EPOQUE { - _EPOQUE() { - EPOQUE = std::chrono::system_clock::now(); - } - std::chrono::system_clock::time_point EPOQUE; -} __EPOQUE__; -} \ No newline at end of file +#include "spdlog/spdlog.h" \ No newline at end of file