diff --git a/Server/src/server.cpp b/Server/src/server.cpp index d98c0d4..2837cb6 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -13,16 +13,10 @@ #include "precomp.hpp" -void _TCPClient(Chattr::TCPSocket sock, Chattr::Address addr); +void _TCPRecvClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, Chattr::Address addr); +void _TCPSendClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, Chattr::Address addr, std::queue packets); int main() { - Chattr::Snowflake flake; - flake.instance = 513; - flake.sequence = 2049; - flake.timestamp = 2199023255553; - spdlog::info("{}", sizeof(Chattr::Snowflake)); - std::cout << std::bitset<64>(flake.snowflake) << "(" << std::hex << flake.snowflake << ")" << std::endl; - return 0 ; struct Chattr::WSAManager wsaManager; auto config = Chattr::ConfigManager::load(); Chattr::log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount); @@ -41,7 +35,7 @@ int main() { serveraddr.set(AF_INET6, in6addr_any, config.listenPort); clientAddr.setType(AF_INET6); } - sock.bind(&serveraddr.addr, serveraddr.length); + sock.bind(serveraddr); sock.listen(SOMAXCONN); #ifdef _WIN32 @@ -53,7 +47,7 @@ int main() { Chattr::ThreadPool threadPool(0); - int returnedIntager = 0; + /*int returnedIntager = 0; int passvalue = 2; threadPool.enqueueJob([](int& i){ spdlog::info("JobTest"); @@ -62,27 +56,110 @@ int main() { return 2; } return 1; - }, returnedIntager, std::ref(passvalue)); + }, returnedIntager, std::ref(passvalue));*/ while (true) { spdlog::info("Waiting for connection..."); sock.accept(clientSock, clientAddr); - threadPool.enqueueJob(_TCPClient, std::move(clientSock), clientAddr); + threadPool.enqueueJob(_TCPRecvClient, std::move(clientSock), clientAddr); } } -void _TCPClient(Chattr::TCPSocket sock, Chattr::Address addr) { - spdlog::info("Connection accepted. [{}]", (std::string)addr); +void _TCPRecvClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, Chattr::Address addr) { + Chattr::Packet pack; + int packetSize = 1500; + int totalRedSize = 0; + int redSize = 0; - char buf[1024]; - - while (true) { - int redSize = sock.recv(buf, 1024, 0); - if (redSize == 0) - break; - std::string recvData(buf, redSize); - spdlog::info("Red size : {}, {}", redSize, recvData); + while (totalRedSize < packetSize) { + redSize = sock.recv(&pack.serialized, 1500 - totalRedSize, 0); + + if (redSize <= 0) { + spdlog::info("Client disconnected. [{}]", (std::string)addr); + return; + } + totalRedSize += redSize; } - spdlog::info("Client disconnected. [{}]", (std::string)addr); + + std::string recvString; + bool packetError = false; + Chattr::DataPostPacket dataPostPacket; + + switch (pack.__data.packetType) { + case Chattr::PacketType::PACKET_POST: + switch (pack.__data.dataType) { + case Chattr::DataType::TEXT: + std::memcpy(&dataPostPacket.serialized, &pack, 1500); + dataPostPacket.convToH(); + recvString = std::string((char *)dataPostPacket.__data.data, dataPostPacket.__data.packetLength - sizeof(std::uint16_t)); + spdlog::info("Red size : {}, {} from : [{}]", redSize, recvString, (std::string)addr); + break; + case Chattr::DataType::BINARY: + break; + default: + 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: + packetError = true; + break; + } + break; + case Chattr::PacketType::PACKET_CONTINUE: + break; + default: + packetError = true; + break; + } + + if (packetError) { + Chattr::ResponsePacket packet; + packet.__data.responseStatusCode = Chattr::ResponseStatusCode::BAD_REQUEST; + std::queue packs; + packet.convToN(); + packs.push(packet); + thread->enqueueJob(_TCPSendClient, std::move(sock), addr, packs); + } + else + thread->enqueueJob(_TCPRecvClient, std::move(sock), addr); +} + +void _TCPSendClient(Chattr::ThreadPool* thread, Chattr::TCPSocket sock, Chattr::Address addr, std::queue packets) { + Chattr::ResponsePacket pack = packets.front(); + packets.pop(); + int packetSize = 1500; + int totalSentSize = 0; + int sentSize = 0; + + while (totalSentSize < packetSize) { + + sentSize = sock.send(&pack.serialized, 1500 - totalSentSize, 0); + + if (sentSize <= 0) { + spdlog::info("Client disconnected. [{}]", (std::string)addr); + return; + } + totalSentSize += sentSize; + } + + if (packets.empty()) + thread->enqueueJob(_TCPRecvClient, std::move(sock), addr); + else + thread->enqueueJob(_TCPSendClient, std::move(sock), addr, packets); } \ No newline at end of file diff --git a/impl/Session/Session.cpp b/impl/Session/Session.cpp index 214d7ee..689d177 100644 --- a/impl/Session/Session.cpp +++ b/impl/Session/Session.cpp @@ -1,28 +1,60 @@ -#include "Session/Session.hpp" - -namespace Chattr { - -Session::Session(Chattr::TCPSocket __sock) { - init(std::move(__sock)); -} - -Session::~Session() { - destruct(); -} - -void Session::init(Chattr::TCPSocket __sock) { - -} - -void Session::destruct() { -} - -int Session::send() { - return -1; -} - -int Session::recv() { - return -1; -} - -} \ No newline at end of file +//#include "Session/Session.hpp" +//#include "Socket/Log.hpp" +//#include "precomp.hpp" +//#include +// +//namespace Chattr { +// +//Session::Session(Chattr::TCPSocket __sock) { +// init(std::move(__sock)); +//} +// +//Session::~Session() { +// destruct(); +//} +// +//void Session::init(Chattr::TCPSocket __sock) { +// sock_ = std::move(__sock); +//} +// +//void Session::destruct() { +//} +// +//TCPSocket Session::reconnect(Chattr::TCPSocket __sock, int maxTry) { +// int retVal = 0; +// int backoffTime = 2; +// +// __sock.destruct(); +// +// spdlog::info("Lost connection."); +// while (maxTry--) { +// backoffTime *= backoffTime; +// spdlog::info("Attempt to reconnect in {}s...", backoffTime); +// std::this_thread::sleep_for(std::chrono::seconds(backoffTime)); +// TCPSocket sock; +// +// retVal = sock.init(__sock.domain); +// if (retVal == INVALID_SOCKET || retVal == SOCKET_ERROR) { +// log::error("init()"); +// continue; +// } +// retVal = sock.connect(__sock.remoteAddr); +// if (retVal == INVALID_SOCKET || retVal == SOCKET_ERROR) { +// log::error("connect()"); +// continue; +// } +// +// return sock; +// } +// return TCPSocket(); +//} +// +//int Session::recv(void* __restrict __buf, size_t __n, int __flags) { +// return -1; +//} +// +//int Session::send(const void* __buf, size_t __n, int __flags) { +// return -1; +//} +// +//} \ No newline at end of file diff --git a/impl/Session/SessionManager.cpp b/impl/Session/SessionManager.cpp new file mode 100644 index 0000000..678c445 --- /dev/null +++ b/impl/Session/SessionManager.cpp @@ -0,0 +1,2 @@ +// #include "Session/SessionManager.hpp" +#include "precomp.hpp" \ No newline at end of file diff --git a/impl/Socket/Log.cpp b/impl/Socket/Log.cpp index 8b5f510..c8d8408 100644 --- a/impl/Socket/Log.cpp +++ b/impl/Socket/Log.cpp @@ -55,11 +55,11 @@ void error(gsl::czstring msg) { (LPSTR)&msgbuf, 0, NULL); - spdlog::critical("[{}] {}", msg, msgbuf); + spdlog::error("[{}] {}", msg, msgbuf); LocalFree(msgbuf); #elif __linux__ gsl::czstring msgbuf = strerror(errno); - spdlog::critical("[{}] {}", msg, msgbuf); + spdlog::error("[{}] {}", msg, msgbuf); #else #error "이 플랫폼은 지원되지 않습니다." #endif diff --git a/impl/Socket/Socket.cpp b/impl/Socket/Socket.cpp index d3ae205..fe1348f 100644 --- a/impl/Socket/Socket.cpp +++ b/impl/Socket/Socket.cpp @@ -12,17 +12,16 @@ Socket::~Socket() { destruct(); } -void Socket::init(int domain, int type, int protocol) { - if (domain == AF_INET) - bindAddr.length = sizeof(sockaddr_in); - else if (domain == AF_INET6) - bindAddr.length = sizeof(sockaddr_in6); +int Socket::init(int domain, int type, int protocol) { + this->domain = domain; sock_ = ::socket(domain, type, protocol); if (sock_ == INVALID_SOCKET) log::critical("socket()"); valid_ = true; + + return 0; } void Socket::destruct() { @@ -33,6 +32,7 @@ void Socket::destruct() { #elif __linux__ ::close(sock_); #endif + valid_ = false; } Socket::operator SOCKET() { @@ -44,7 +44,7 @@ Socket::operator SOCKET() { return INVALID_SOCKET; } -void Socket::set(const SOCKET __sock) { +void Socket::set(const SOCKET __sock, int __domain) { if (__sock == INVALID_SOCKET) log::critical("socket()"); @@ -54,32 +54,12 @@ void Socket::set(const SOCKET __sock) { valid_ = true; }; -void Socket::bind(sockaddr *__addr) { - bind((struct sockaddr *)__addr, sizeof(sockaddr)); -} - -void Socket::bind(sockaddr *__addr, socklen_t __len) { - bindAddr.length = __len; - std::memcpy(&bindAddr, __addr, __len); - int retVal = ::bind(sock_, __addr, __len); +int Socket::bind(Address __addr) { + bindAddr = __addr; + int retVal = ::bind(sock_, &__addr.addr, __addr.length); if (retVal == INVALID_SOCKET) log::critical("bind()"); -} - -void Socket::bind(sockaddr_in *__addr) { - bind((struct sockaddr *)__addr, sizeof(sockaddr_in)); -} - -void Socket::bind(sockaddr_in *__addr, socklen_t __len) { - bind((struct sockaddr *)__addr, __len); -} - -void Socket::bind(sockaddr_in6 *__addr) { - bind((struct sockaddr *)__addr, sizeof(sockaddr_in6)); -} - -void Socket::bind(sockaddr_in6 *__addr, socklen_t __len) { - bind((struct sockaddr *)__addr, __len); + return retVal; } int Socket::recvfrom(void *__restrict __buf, size_t __n, int __flags, struct Address& __addr) { diff --git a/impl/Socket/TCPSocket.cpp b/impl/Socket/TCPSocket.cpp index 911d805..0462f19 100644 --- a/impl/Socket/TCPSocket.cpp +++ b/impl/Socket/TCPSocket.cpp @@ -4,27 +4,29 @@ namespace Chattr { -void TCPSocket::init(int domain) { - init(domain, SOCK_STREAM, 0); - valid_ = true; +int TCPSocket::init(int domain) { + return init(domain, SOCK_STREAM, 0); } -void TCPSocket::listen(int __n) { +int TCPSocket::listen(int __n) { int retVal = ::listen(sock_, __n); if (retVal == INVALID_SOCKET) - log::critical("listen()"); + log::error("listen()"); + return retVal; } void TCPSocket::accept(TCPSocket& newSock, Address& __addr) { - newSock.set(::accept(sock_, &__addr.addr, &__addr.length)); + newSock.set(::accept(sock_, &__addr.addr, &__addr.length), domain); if (newSock == INVALID_SOCKET) - log::critical("accept()"); + log::error("accept()"); } -void TCPSocket::connect(Chattr::Address& serveraddr) { +int TCPSocket::connect(Address& serveraddr) { int retVal = ::connect(sock_, (struct sockaddr *)&serveraddr.addr, serveraddr.length); + remoteAddr = serveraddr; if (retVal == INVALID_SOCKET) - log::critical("connect()"); + log::error("connect()"); + return retVal; } int TCPSocket::recv(void *__restrict __buf, size_t __n, int __flags) { diff --git a/impl/Utils/StringTokenizer.cpp b/impl/Utils/StringTokenizer.cpp index 0f90641..2720ccb 100644 --- a/impl/Utils/StringTokenizer.cpp +++ b/impl/Utils/StringTokenizer.cpp @@ -11,7 +11,7 @@ void StringTokenizer::set(gsl::czstring string, std::uint32_t size) { bool token = false; bool quote = false, doubleQuote = false; - for (int i = 0; i < size; i++) { + for (std::uint32_t i = 0; i < size; i++) { if (string[i] == ' ' && token != true) continue; diff --git a/include/Packet/Packet.hpp b/include/Packet/Packet.hpp index ca75eb2..33bf86b 100644 --- a/include/Packet/Packet.hpp +++ b/include/Packet/Packet.hpp @@ -29,13 +29,16 @@ enum class DataType : std::uint8_t { class alignas(4) Packet { public: + Packet() { + memset(serialized, 0, 1500); + } union { struct { PacketType packetType; RequestType requestType; DataType dataType; std::uint16_t packetLength; - std::uint8_t data[1484]; + std::uint8_t data[1495]; } __data; std::uint8_t serialized[1500]; }; @@ -90,6 +93,16 @@ public: } __data; std::uint8_t serialized[1500]; }; + std::uint8_t* convToN() { + __data.packetLength = ::htons(__data.packetLength); + __data.roomCount = ::htonl(__data.roomCount); + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + __data.roomCount = ::ntohl(__data.roomCount); + return serialized; + } }; class alignas(4) RoomJoinRequestPacket : public Packet { @@ -128,7 +141,6 @@ public: RequestType requestType; DataType dataType; std::uint16_t packetLength; - std::uint32_t usersCount; std::uint8_t name[]; } __data; std::uint8_t serialized[1500]; @@ -143,16 +155,31 @@ public: RequestType requestType; DataType dataType; std::uint16_t packetLength; - std::uint8_t name[]; + 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; + } }; class alignas(4) ContinuePacket : public Packet { public: union { struct { + PacketType packetType; + std::uint8_t padding[2]; std::uint16_t packetLength; std::uint8_t data[]; } __data; @@ -174,6 +201,41 @@ enum class ResponseStatusCode : std::uint16_t { }; class alignas(4) ResponsePacket : public Packet { +public: + union { + struct { + PacketType packetType; + RequestType requestType; + DataType dataType; + std::uint16_t packetLength; + ResponseStatusCode responseStatusCode; + std::uint8_t data[]; + } __data; + std::uint8_t serialized[1500]; + }; + std::uint8_t* convToN() { + __data.packetLength = ::htons(__data.packetLength); + __data.responseStatusCode = (ResponseStatusCode)::htons((std::uint16_t)__data.responseStatusCode); + return serialized; + } + std::uint8_t* convToH() { + __data.packetLength = ::ntohs(__data.packetLength); + __data.responseStatusCode = (ResponseStatusCode)::ntohs((std::uint16_t)__data.responseStatusCode); + return serialized; + } +}; + +//enum class RequestType : std::uint8_t { +// LOGIN, +// ROOM_CREATE, +// ROOM_LIST, +// ROOM_JOIN, +// ROOM_EXIT, +// USERS_LIST, +// DATA +//}; + +class alignas(4) LoginResponsePacket : public ResponsePacket { public: union { struct { diff --git a/include/Session/Session.hpp b/include/Session/Session.hpp deleted file mode 100644 index 2d65531..0000000 --- a/include/Session/Session.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once -#include "Socket/TCPSocket.hpp" -#include "Utils/Snowflake.hpp" -#include - -namespace Chattr { -class Session { -public: - Session(Chattr::TCPSocket __sock); - ~Session(); - - void init(Chattr::TCPSocket __sock); - void destruct(); - - int send(); - int recv(); - - Session(const Session&) = delete; - Session& operator=(Session&) = delete; - -private: - Chattr::TCPSocket sock_; - struct Snowflake sessId_; -}; -} \ No newline at end of file diff --git a/include/Socket/IOCP.hpp b/include/Socket/IOCP.hpp index fde4e84..40fce48 100644 --- a/include/Socket/IOCP.hpp +++ b/include/Socket/IOCP.hpp @@ -9,7 +9,8 @@ public: void init(std::shared_ptr __IOCPThread); - void recv(); + int recv(void* __restrict __buf, size_t __n, int __flags); + int send(const void* __buf, size_t __n, int __flags); private: std::shared_ptr IOCPThread_; diff --git a/include/Socket/Socket.hpp b/include/Socket/Socket.hpp index fad4bb9..3f24e36 100644 --- a/include/Socket/Socket.hpp +++ b/include/Socket/Socket.hpp @@ -11,22 +11,13 @@ public: Socket(int domain, int type, int protocol); ~Socket(); - void init(int domain, int type, int protocol); + int init(int domain, int type, int protocol); void destruct(); operator SOCKET(); - void set(const SOCKET); + void set(const SOCKET __sock, int __domain); - void bind(sockaddr *__addr); - void bind(sockaddr *__addr, socklen_t __len); - - //IPV4 - void bind(sockaddr_in *__addr); - void bind(sockaddr_in *__addr, socklen_t __len); - - //IPV6 - void bind(sockaddr_in6 *__addr); - void bind(sockaddr_in6 *__addr, socklen_t __len); + int bind(Address __addr); int recvfrom(void *__restrict __buf, size_t __n, int __flags, struct Address& __addr); int sendto(const void *__buf, size_t __n, int __flags, struct Address __addr); @@ -37,6 +28,9 @@ public: Socket& operator=(Socket&&); struct Address bindAddr = {}; + struct Address remoteAddr = {}; + + int domain = 0; protected: bool valid_ = false; SOCKET sock_ = INVALID_SOCKET; diff --git a/include/Socket/TCPSocket.hpp b/include/Socket/TCPSocket.hpp index 2e625cd..83d0082 100644 --- a/include/Socket/TCPSocket.hpp +++ b/include/Socket/TCPSocket.hpp @@ -7,10 +7,10 @@ class TCPSocket : public Socket { public: using Socket::Socket; using Socket::init; - void init(int domain); - void listen(int __n); + int init(int domain); + int listen(int __n); void accept(TCPSocket& newSock, Address& addr); - void connect(Chattr::Address& serveraddr); + int connect(Chattr::Address& serveraddr); int recv(void *__restrict __buf, size_t __n, int __flags); int send(const void *__buf, size_t __n, int __flags); }; diff --git a/include/Utils/ThreadPool.hpp b/include/Utils/ThreadPool.hpp index bf6a62a..b903e03 100644 --- a/include/Utils/ThreadPool.hpp +++ b/include/Utils/ThreadPool.hpp @@ -18,7 +18,7 @@ public: void init(std::uint32_t numThreads); template - requires (!std::is_void_v>) + requires (!std::is_void_v>) int enqueueJob(_Callable&& __job, std::invoke_result_t<_Callable, _Args...>& retVal, _Args&&... __args) { if (terminate_) { spdlog::error("Cannot run jobs on threads that terminating..."); @@ -26,8 +26,8 @@ public: } std::lock_guard lock(jobQueueMutex); - auto boundFunc = [&retVal, __job = std::move(__job), ... __args = std::move(__args)]() mutable { - retVal = __job(std::move(__args)...); + auto boundFunc = [this, &retVal, __job = std::move(__job), ... __args = std::move(__args)]() mutable { + retVal = __job(this, std::move(__args)...); }; auto task = std::packaged_task(std::move(boundFunc)); jobs_.push(std::move(task)); @@ -36,7 +36,7 @@ public: return 0; } template - requires std::is_void_v> + requires std::is_void_v> int enqueueJob(_Callable&& __job, _Args&&... __args) { if (terminate_) { spdlog::error("Cannot run jobs on threads that terminating..."); @@ -44,8 +44,8 @@ public: } std::lock_guard lock(jobQueueMutex); - auto boundFunc = [__job = std::move(__job), ... __args = std::move(__args)]() mutable { - __job(std::move(__args)...); + auto boundFunc = [this, __job = std::move(__job), ... __args = std::move(__args)]() mutable { + __job(this, std::move(__args)...); }; auto task = std::packaged_task(std::move(boundFunc)); jobs_.push(std::move(task)); diff --git a/include/precomp.hpp b/include/precomp.hpp index 73cb206..0082246 100644 --- a/include/precomp.hpp +++ b/include/precomp.hpp @@ -19,5 +19,15 @@ #error "이 플랫폼은 지원되지 않습니다." #endif +#include #include -#include "spdlog/spdlog.h" \ No newline at end of file +#include "spdlog/spdlog.h" + +namespace Chattr { + struct _EPOQUE_ { + _EPOQUE_() { + EPOQUE = std::chrono::system_clock::now(); + } + std::chrono::system_clock::time_point EPOQUE; + } _EPOQUE_; +} \ No newline at end of file