diff --git a/.vscode/settings.json b/.vscode/settings.json index 3ca687a..a988a14 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -71,6 +71,14 @@ "queue": "cpp", "stack": "cpp", "fstream": "cpp", - "regex": "cpp" + "regex": "cpp", + "assert": "cpp", + "pointers": "cpp", + "future": "cpp", + "zstring": "cpp", + "set": "cpp", + "util": "cpp", + "expected": "cpp", + "complex": "cpp" } } \ No newline at end of file diff --git a/Client/src/client.cpp b/Client/src/client.cpp index dbfa5d5..d073399 100644 --- a/Client/src/client.cpp +++ b/Client/src/client.cpp @@ -7,11 +7,9 @@ int main() { Chattr::TCPSocket sock; sock.init(AF_INET6); - Chattr::Address serveraddr; - serveraddr.addr_in6.sin6_family = AF_INET6; - inet_pton(AF_INET6, "::1", &serveraddr.addr_in6.sin6_addr); - serveraddr.addr_in6.sin6_port = htons(9010); - serveraddr.length = sizeof(sockaddr_in6); + Chattr::Address serveraddr(AF_INET6, "::1", 9010); sock.connect(serveraddr); + + spdlog::info("Connection established from {}, {}", sock, (std::string)serveraddr); } \ No newline at end of file diff --git a/Server/src/Chattering.log b/Server/src/Chattering.log deleted file mode 100644 index 848a256..0000000 --- a/Server/src/Chattering.log +++ /dev/null @@ -1,12 +0,0 @@ -[2025-04-24 21:34:04.752] [Chattering Logger] [info] thread? -[2025-04-24 21:34:04.752] [Chattering Logger] [info] Waiting for connection... -[2025-04-24 21:34:24.926] [Chattering Logger] [info] thread? -[2025-04-24 21:34:24.926] [Chattering Logger] [info] Waiting for connection... -[2025-04-24 21:34:39.658] [Chattering Logger] [info] thread? -[2025-04-24 21:34:39.658] [Chattering Logger] [info] Waiting for connection... -[2025-04-24 21:34:48.422] [Chattering Logger] [info] Waiting for connection... -[2025-04-24 21:34:48.422] [Chattering Logger] [info] thread? -[2025-04-24 21:34:49.422] [Chattering Logger] [info] thread? -[2025-04-24 21:35:32.526] [Chattering Logger] [info] thread? -[2025-04-24 21:35:33.526] [Chattering Logger] [info] thread? -[2025-04-24 21:35:33.526] [Chattering Logger] [info] Waiting for connection... diff --git a/Server/src/config.json b/Server/src/config.json deleted file mode 100644 index 5d7237d..0000000 --- a/Server/src/config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "IP Version" : 6, - "Listen Port" : 9010, - "LogLevel" : 1, - "LogfileCount" : 5, - "LogfileName" : "Chattering.log", - "LogfileSize" : 4294967295 -} \ No newline at end of file diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 9597daa..563f709 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -2,34 +2,27 @@ #include "Socket/Log.hpp" #include "Utils/ConfigManager.hpp" #include "Utils/Thread.hpp" +#include "Utils/StringTokenizer.hpp" #include "precomp.hpp" +void _TCPClient(Chattr::TCPSocket sock, Chattr::Address addr); + int main() { auto config = Chattr::ConfigManager::load(); Chattr::log::setDefaultLogger(config.logLevel, config.logFileName, config.logfileSize, config.logfileCount); struct Chattr::TCPSocket sock; + struct Chattr::Address serveraddr; if (config.ipVersion == 4) { sock.init(AF_INET); - - struct Chattr::Address serveraddr; - serveraddr.addr_in.sin_family = AF_INET; - serveraddr.addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - serveraddr.addr_in.sin_port = htons(config.listenPort); - - sock.bind(&serveraddr.addr_in); + serveraddr.set(AF_INET, INADDR_ANY, config.listenPort); } - else { + else if (config.ipVersion == 6) { sock.init(AF_INET6); - - struct Chattr::Address serveraddr; - serveraddr.addr_in6.sin6_family = AF_INET6; - serveraddr.addr_in6.sin6_addr = in6addr_any; - serveraddr.addr_in6.sin6_port = htons(config.listenPort); - - sock.bind(&serveraddr.addr_in6); + serveraddr.set(AF_INET6, in6addr_any, config.listenPort); } + sock.bind(&serveraddr.addr, serveraddr.length); sock.listen(SOMAXCONN); struct Chattr::TCPSocket clientSock; struct Chattr::Address clientAddr; @@ -39,12 +32,15 @@ int main() { else clientAddr.length = sizeof(sockaddr_in6); - Chattr::Thread t1([]() { - spdlog::info("thread?"); - sleep(1); - spdlog::info("thread?"); - }); + while (true) { + spdlog::info("Waiting for connection..."); + sock.accept(clientSock, clientAddr); + + Chattr::Thread thread_(_TCPClient, std::move(clientSock), clientAddr); + } +} + +void _TCPClient(Chattr::TCPSocket sock, Chattr::Address addr) { + spdlog::info("Connection accepted! from: {}, {}", sock, (std::string)addr); - spdlog::info("Waiting for connection..."); - // sock.accept(clientSock, clientAddr); } \ No newline at end of file diff --git a/impl/Socket/Socket.cpp b/impl/Socket/Socket.cpp index 25ced43..4ce8244 100644 --- a/impl/Socket/Socket.cpp +++ b/impl/Socket/Socket.cpp @@ -22,14 +22,7 @@ Socket::Socket(int domain, int type, int protocol) { } Socket::~Socket() { - if (!valid_) - return; -#ifdef _WIN32 - closesocket(sock_); - WSACleanup(); -#elif __linux__ - ::close(sock_); -#endif + destruct(); } void Socket::init(int domain, int type, int protocol) { @@ -45,6 +38,17 @@ void Socket::init(int domain, int type, int protocol) { valid_ = true; } +void Socket::destruct() { + if (!valid_) + return; +#ifdef _WIN32 + closesocket(sock_); + WSACleanup(); +#elif __linux__ + ::close(sock_); +#endif +} + Socket::operator SOCKET() const { if (valid_) return sock_; @@ -52,30 +56,25 @@ Socket::operator SOCKET() const { return INVALID_SOCKET; } -void Socket::move(const SOCKET __sock) { - if (__sock == INVALID_SOCKET) +void Socket::move(const SOCKET __sock) +{ + if (__sock == INVALID_SOCKET) log::critical("socket()"); - if (valid_) { -#ifdef _WIN32 - closesocket(sock_); - WSACleanup(); -#elif __linux__ - ::close(sock_); -#endif - } - else { -#ifdef _WIN32 - WSADATA wsa; - if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) - log::critical("WSAStartup()"); -#endif - } + destruct(); sock_ = __sock; valid_ = true; }; +Socket& Socket::move() { + std::shared_ptr socket = std::make_shared(); + valid_ = false; + socket->move(sock_); + + return *socket; +}; + void Socket::bind(sockaddr *__addr) { bind((struct sockaddr *)__addr, sizeof(sockaddr)); } @@ -104,4 +103,20 @@ void Socket::bind(sockaddr_in6 *__addr, socklen_t __len) { bind((struct sockaddr *)__addr, __len); } -} \ No newline at end of file +Socket::Socket(Socket&& other_) { + other_.valid_ = false; + sock_ = other_.sock_; + valid_ = true; +} + +Socket& Socket::operator=(Socket && other_) { + other_.valid_ = false; + sock_ = other_.sock_; + valid_ = true; + + return *this; +} + +} + + diff --git a/impl/Socket/TCPSocket.cpp b/impl/Socket/TCPSocket.cpp index 39cd75d..9bcd53b 100644 --- a/impl/Socket/TCPSocket.cpp +++ b/impl/Socket/TCPSocket.cpp @@ -21,8 +21,8 @@ void TCPSocket::accept(TCPSocket& newSock, Address& __addr) { log::critical("accept()"); } -void TCPSocket::connect(Chattr::Address serveraddr) { - int retVal = ::connect(sock_, (struct sockaddr *)&serveraddr, serveraddr.length); +void TCPSocket::connect(Chattr::Address& serveraddr) { + int retVal = ::connect(sock_, (struct sockaddr *)&serveraddr.addr, serveraddr.length); if (retVal == INVALID_SOCKET) log::critical("connect()"); } diff --git a/include/Socket/Address.hpp b/include/Socket/Address.hpp index ee35196..a0a4391 100644 --- a/include/Socket/Address.hpp +++ b/include/Socket/Address.hpp @@ -1,13 +1,101 @@ #pragma once #include "precomp.hpp" +#include namespace Chattr { struct Address { Address() { + zeroFill(); + } + + Address(int type, gsl::czstring presentationAddr, std::uint16_t port) { + set(type, presentationAddr, port); + } + + void zeroFill() { memset(&addr_in6, 0, sizeof(addr_in6)); } + void set(int type, gsl::czstring presentationAddr, std::uint16_t port) { + zeroFill(); + + if (type == AF_INET) { + addr_in.sin_family = AF_INET; + ::inet_pton(AF_INET, presentationAddr, &addr_in.sin_addr); + addr_in.sin_port = htons(port); + length = sizeof(sockaddr_in); + } else if (type == AF_INET6) { + addr_in6.sin6_family = AF_INET6; + ::inet_pton(AF_INET6, presentationAddr, &addr_in6.sin6_addr); + addr_in6.sin6_port = htons(port); + length = sizeof(sockaddr_in6); + } + } + + void set(int type, in_addr_t addr, std::uint16_t port) { + zeroFill(); + + if (type == AF_INET) { + addr_in.sin_family = AF_INET; + addr_in.sin_addr.s_addr = htonl(addr); + addr_in.sin_port = htons(port); + length = sizeof(sockaddr_in); + } + } + + void set(int type, in_addr addr, std::uint16_t port) { + zeroFill(); + + if (type == AF_INET) { + addr_in.sin_family = AF_INET; + addr_in.sin_addr = addr; + addr_in.sin_port = htons(port); + length = sizeof(sockaddr_in); + } + } + + void set(int type, in6_addr addr, std::uint16_t port) { + zeroFill(); + + if (type == AF_INET6) { + addr_in6.sin6_family = AF_INET6; + addr_in6.sin6_addr = addr; + addr_in6.sin6_port = htons(port); + length = sizeof(sockaddr_in6); + } + } + + operator std::string() { + std::optional port = getPort(); + + if (!port) + return std::string(); + + if (length == sizeof(addr_in)) { + char addrStr[INET_ADDRSTRLEN]; + ::inet_ntop(AF_INET, &addr_in.sin_addr, addrStr, sizeof(addrStr)); + + return std::format("{}:{}", addrStr, port.value()); + } else if (length == sizeof(addr_in6)) { + char addrStr[INET6_ADDRSTRLEN]; + ::inet_ntop(AF_INET6, &addr_in6.sin6_addr, addrStr, sizeof(addrStr)); + + return std::format("{}:{}", addrStr, port.value()); + } + + return std::string(); + } + + std::optional getPort() { + if (length == sizeof(addr_in)) + return ntohs(addr_in.sin_port); + else if (length == sizeof(addr_in6)) + return ntohs(addr_in6.sin6_port); + else + return std::nullopt; + } + union { struct sockaddr addr; struct sockaddr_in addr_in; diff --git a/include/Socket/Socket.hpp b/include/Socket/Socket.hpp index 4bb5370..adc9a0e 100644 --- a/include/Socket/Socket.hpp +++ b/include/Socket/Socket.hpp @@ -11,9 +11,11 @@ public: ~Socket(); void init(int domain, int type, int protocol); + void destruct(); operator SOCKET() const; void move(const SOCKET); + Socket& move(); void bind(sockaddr *__addr); void bind(sockaddr *__addr, socklen_t __len); @@ -27,7 +29,9 @@ public: void bind(sockaddr_in6 *__addr, socklen_t __len); Socket(const Socket&) = delete; + Socket(Socket&&); Socket& operator=(const Socket&) = delete; + Socket& operator=(Socket&&); struct Address bindAddr = {}; protected: diff --git a/include/Socket/TCPSocket.hpp b/include/Socket/TCPSocket.hpp index 2a5ec71..a39670e 100644 --- a/include/Socket/TCPSocket.hpp +++ b/include/Socket/TCPSocket.hpp @@ -11,7 +11,7 @@ public: void init(int domain); void listen(int __n); void accept(TCPSocket& newSock, Address& addr); - void connect(Chattr::Address serveraddr); + void connect(Chattr::Address& serveraddr); }; } \ No newline at end of file diff --git a/include/Utils/StringTokenizer.hpp b/include/Utils/StringTokenizer.hpp new file mode 100644 index 0000000..4213a4b --- /dev/null +++ b/include/Utils/StringTokenizer.hpp @@ -0,0 +1,19 @@ +#pragma once +#include "precomp.hpp" +#include + +namespace Chattr { +class StringTokenizer { +public: + StringTokenizer() {} + StringTokenizer(gsl::czstring string, std::uint32_t size); + + void set(gsl::czstring string, std::uint32_t size); + std::vector get(); + + operator std::vector(); +private: + std::queue tokens; + std::queue tokens_length; +}; +} \ No newline at end of file diff --git a/include/Utils/Thread.hpp b/include/Utils/Thread.hpp index da1b5b9..f4a8412 100644 --- a/include/Utils/Thread.hpp +++ b/include/Utils/Thread.hpp @@ -8,6 +8,7 @@ #error "이 플랫폼은 지원되지 않습니다." #endif #include +#include namespace Chattr { @@ -15,23 +16,26 @@ class Thread { public: #ifdef _WIN32 static unsigned __stdcall thread_func(LPVOID param) { - std::unique_ptr> func(static_cast*>(param)); - (*func)(); + auto task(static_cast*>(param)); + (*task)(); + delete task; return 0; } #elif __linux__ static void* thread_func(void *param) { - std::unique_ptr> func(static_cast*>(param)); - (*func)(); + auto task(static_cast*>(param)); + (*task)(); + delete task; return 0; } #endif - template - Thread(Callable&& f, Args&&... args) { - auto boundFunc = std::bind(std::forward(f), std::forward(args)...); - - auto funcPtr = new std::function(boundFunc); - + template + requires (!std::is_same_v, Thread>) //복사 생성하면 안 되므로 + Thread(_Callable&& __f, _Args&&... __args) { + auto boundFunc = [__f = std::move(__f), ... __args = std::move(__args)]() mutable { + __f(std::move(__args)...); + }; + auto funcPtr = new std::packaged_task(std::move(boundFunc)); #ifdef _WIN32 handle_ = (HANDLE)_beginthreadex(nullptr, 0, thread_func, funcPtr, 0, nullptr); #elif __linux__