diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..ad5ee5b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,11 @@ +{ + "configurations": [ + { + "compileCommands": "build/compile_commands.json", + "intelliSenseMode": "linux-gcc-x64", + "cStandard": "c17", + "cppStandard": "c++20" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 9e6766f..c66a6ef 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "files.associations": { - "assert": "cpp", - "zstring": "cpp", + "sstream": "cpp", + "iosfwd": "cpp", "ostream": "cpp", "cctype": "cpp", "cmath": "cpp", @@ -45,14 +45,12 @@ "format": "cpp", "initializer_list": "cpp", "iomanip": "cpp", - "iosfwd": "cpp", "istream": "cpp", "limits": "cpp", "mutex": "cpp", "new": "cpp", "semaphore": "cpp", "span": "cpp", - "sstream": "cpp", "stdexcept": "cpp", "stop_token": "cpp", "streambuf": "cpp", @@ -71,6 +69,8 @@ "locale": "cpp", "print": "cpp", "queue": "cpp", - "stack": "cpp" + "stack": "cpp", + "assert": "cpp", + "zstring": "cpp" } } \ No newline at end of file diff --git a/Server/CMakeLists.txt b/Server/CMakeLists.txt index a734f78..4c9e48c 100644 --- a/Server/CMakeLists.txt +++ b/Server/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.5) set(PROJECT_NAME "Server") set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project(${PROJECT_NAME} CXX) @@ -23,6 +24,14 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(GSL) +FetchContent_Declare( + JSONCPP + GIT_REPOSITORY "https://github.com/open-source-parsers/jsoncpp.git" + GIT_TAG "1.9.6" + GIT_SHALLOW ON +) +FetchContent_MakeAvailable(JSONCPP) + file(GLOB_RECURSE additional_sources CONFIGURE_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/../impl/*.cpp" ) @@ -33,6 +42,7 @@ add_executable(${PROJECT_NAME} ) target_link_libraries(${PROJECT_NAME} PRIVATE Microsoft.GSL::GSL) target_link_libraries(${PROJECT_NAME} PRIVATE spdlog) +target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp_lib) if(WIN32) target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32) diff --git a/Server/src/server.cpp b/Server/src/server.cpp index 4ac3c62..1926c83 100644 --- a/Server/src/server.cpp +++ b/Server/src/server.cpp @@ -1,15 +1,68 @@ -#include -#include "Socket/Socket_Init.hpp" +#include "Socket/Socket.hpp" +#include "Socket/Log.hpp" #include "precomp.hpp" +#include +#include +#include +#include int main() { - struct Chattr::Socket_Init sock(AF_INET, SOCK_DGRAM, 0); + Json::Value configJsonRoot; + std::uint32_t ipVersion = 0; + std::uint32_t listenPort = 0; + spdlog::level::level_enum logLevel; + gsl::czstring logFileName; + std::uint32_t logfileSize; + std::uint32_t logfileCount; + + std::ifstream config("config.json", std::ifstream::binary); + if (!config.is_open()) { + std::ofstream defaultConfig("config.json", std::ios::out); + configJsonRoot["IP Version"] = 6; + configJsonRoot["Listen Port"] = 9010; + configJsonRoot["LogLevel"] = 1; + configJsonRoot["LogfileName"] = "Chattering.log"; + configJsonRoot["LogfileSize"] = UINT32_MAX; + configJsonRoot["LogfileCount"] = 5; + defaultConfig << configJsonRoot; + defaultConfig.close(); + spdlog::critical("\"config.json\" is missing. Default configuration has been written."); + std::exit(EXIT_FAILURE); + } + try { + config >> configJsonRoot; + + ipVersion = configJsonRoot["IP Version"].asInt(); + if (ipVersion != 4 && ipVersion != 6) + throw std::runtime_error("Invalid IP Version."); + + listenPort = configJsonRoot["Listen Port"].asInt(); + if (listenPort < 0 || listenPort > 65535) + throw std::runtime_error("Invalid listen port."); + + int ll_ = configJsonRoot["LogLevel"].asInt(); + if (ll_ >= 0 && ll_ < spdlog::level::n_levels) + logLevel = (spdlog::level::level_enum)ll_; + else + throw std::runtime_error("Invalid log level."); + + logFileName = configJsonRoot["LogfileName"].asCString(); + logfileSize = configJsonRoot["LogfileSize"].asUInt(); + logfileCount = configJsonRoot["LogfileCount"].asUInt(); + } + catch (Json::RuntimeError e) { + spdlog::critical(std::string(std::string("[Json Error: ]") + e.what()).c_str()); + std::exit(EXIT_FAILURE); + } + + Chattr::log::setDefaultLogger(logLevel, logFileName, logfileSize, logfileCount); + + struct Chattr::Socket sock(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in serveraddr = {}; serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(9010); - sock.bind(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); - std::cout << sock << std::endl; + sock.bind(sock, &serveraddr); } \ No newline at end of file diff --git a/impl/Socket/Log.cpp b/impl/Socket/Log.cpp index a27f09c..a2b53ad 100644 --- a/impl/Socket/Log.cpp +++ b/impl/Socket/Log.cpp @@ -1,13 +1,28 @@ #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" -#include "spdlog/spdlog.h" namespace Chattr::log { -void critical(gsl::czstring msg, bool bShowDBGMessage) { - if (!bShowDBGMessage) - spdlog::critical("{}", msg); - else { +void setDefaultLogger(spdlog::level::level_enum logLevel, gsl::czstring logFileName, std::uint32_t logFileSize, std::uint32_t logFileCount) { + std::vector sinks; + sinks.push_back(std::make_shared()); + sinks.push_back(std::make_shared(logFileName, logFileSize, logFileCount, false)); +#ifdef _WIN32 + sinks.push_back(std::make_shared()); +#endif + auto chatteringLogger = std::make_shared("Chattering Logger", begin(sinks), end(sinks)); + chatteringLogger->set_level(logLevel); + spdlog::set_default_logger(chatteringLogger); +} + +void critical(gsl::czstring msg) { #ifdef _WIN32 gsl::zstring msgbuf = nullptr; FormatMessageA( @@ -26,14 +41,10 @@ void critical(gsl::czstring msg, bool bShowDBGMessage) { #else #error "이 플랫폼은 지원되지 않습니다." #endif - } std::exit(EXIT_FAILURE); } -void error(gsl::czstring msg, bool bShowDBGMessage) { - if (!bShowDBGMessage) - spdlog::critical("{}", msg); - else { +void error(gsl::czstring msg) { #ifdef _WIN32 gsl::zstring msgbuf = nullptr; FormatMessageA( @@ -52,7 +63,6 @@ void error(gsl::czstring msg, bool bShowDBGMessage) { #else #error "이 플랫폼은 지원되지 않습니다." #endif - } } } \ No newline at end of file diff --git a/impl/Socket/Socket.cpp b/impl/Socket/Socket.cpp new file mode 100644 index 0000000..81a25f5 --- /dev/null +++ b/impl/Socket/Socket.cpp @@ -0,0 +1,64 @@ +#include "Socket/Socket.hpp" +#include "Socket/Log.hpp" +#include "precomp.hpp" + +namespace Chattr { + +Socket::Socket(int domain, int type, int protocol) { +#ifdef _WIN32 + WSADATA wsa; + if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) + log::critical("WSAStartup()"); +#endif + sock_ = ::socket(domain, type, protocol); + if (sock_ == INVALID_SOCKET) + log::critical("socket()"); + + valid_ = true; +} + +Socket::~Socket() { + if (!valid_) + return; +#ifdef _WIN32 + closesocket(sock_); + WSACleanup(); +#elif __linux__ + ::close(sock_); +#endif +} + +Socket::operator SOCKET() const { + if (valid_) + return sock_; + spdlog::critical("No valid socket created."); + return INVALID_SOCKET; +}; + +void Socket::bind(int __fd, const sockaddr *__addr) { + bind(__fd, (struct sockaddr *)__addr, sizeof(*__addr)); +} + +void Socket::bind(int __fd, const sockaddr *__addr, socklen_t __len) { + int retVal = ::bind(__fd, __addr, __len); + if (retVal == INVALID_SOCKET) + log::critical("bind()"); +} + +void Socket::bind(int __fd, const sockaddr_in *__addr) { + bind(__fd, (struct sockaddr *)__addr, sizeof(*__addr)); +} + +void Socket::bind(int __fd, const sockaddr_in *__addr, socklen_t __len) { + bind(__fd, (struct sockaddr *)__addr, __len); +} + +void Socket::bind(int __fd, const sockaddr_in6 *__addr) { + bind(__fd, (struct sockaddr *)__addr, sizeof(*__addr)); +} + +void Socket::bind(int __fd, const sockaddr_in6 *__addr, socklen_t __len) { + bind(__fd, (struct sockaddr *)__addr, __len); +} + +} \ No newline at end of file diff --git a/impl/Socket/Socket_Init.cpp b/impl/Socket/Socket_Init.cpp deleted file mode 100644 index 832e235..0000000 --- a/impl/Socket/Socket_Init.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "Socket/Socket_Init.hpp" -#include "Socket/Log.hpp" -#include "precomp.hpp" - -namespace Chattr { - -Socket_Init::Socket_Init(std::int32_t domain, std::int32_t type, std::int32_t protocol) -{ -#ifdef _WIN32 - WSADATA wsa; - if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) - log::critical("WSAStartup()"); -#endif - sock_ = socket(domain, type, protocol); - if (sock_ == INVALID_SOCKET) - log::critical("socket()"); - - valid_ = true; -} - -Socket_Init::~Socket_Init() { - if (!valid_) - return; -#ifdef _WIN32 - closesocket(sock_); - WSACleanup(); -#elif __linux__ - close(sock_); -#endif -} - -Socket_Init::operator SOCKET() const { - if (valid_) - return sock_; - log::critical("No valid socket created.", false); - return INVALID_SOCKET; -}; - -void Socket_Init::bind(int __fd, const sockaddr *__addr, socklen_t __len) { - int retVal = ::bind(__fd, __addr, __len); - if (retVal == INVALID_SOCKET) - log::critical("bind()"); -} - -} \ No newline at end of file diff --git a/include/Socket/Log.hpp b/include/Socket/Log.hpp index 40f1623..b8ece9c 100644 --- a/include/Socket/Log.hpp +++ b/include/Socket/Log.hpp @@ -2,6 +2,7 @@ #include "precomp.hpp" namespace Chattr::log { -void critical(gsl::czstring msg, bool bShowDBGMessage = true); -void error(gsl::czstring msg, bool bShowDBGMessage = true); +void setDefaultLogger(spdlog::level::level_enum logLevel, gsl::czstring logFileName, std::uint32_t logFileSize, std::uint32_t logFileCount); +void critical(gsl::czstring msg); +void error(gsl::czstring msg); } \ No newline at end of file diff --git a/include/Socket/Socket.hpp b/include/Socket/Socket.hpp new file mode 100644 index 0000000..cbe3dfe --- /dev/null +++ b/include/Socket/Socket.hpp @@ -0,0 +1,32 @@ +#pragma once +#include "precomp.hpp" + +namespace Chattr { + +class Socket { +public: + Socket() {} + Socket(int domain, int type, int protocol); + ~Socket(); + + operator SOCKET() const; + + void bind(int __fd, const sockaddr *__addr); + void bind(int __fd, const sockaddr *__addr, socklen_t __len); + + //IPV4 + void bind(int __fd, const sockaddr_in *__addr); + void bind(int __fd, const sockaddr_in *__addr, socklen_t __len); + + //IPV6 + void bind(int __fd, const sockaddr_in6 *__addr); + void bind(int __fd, const sockaddr_in6 *__addr, socklen_t __len); + + Socket(const Socket&) = delete; + Socket& operator=(const Socket&) = delete; +private: + bool valid_ = false; + SOCKET sock_ = INVALID_SOCKET; +}; + +} \ No newline at end of file diff --git a/include/Socket/Socket_Init.hpp b/include/Socket/Socket_Init.hpp deleted file mode 100644 index 7591ac3..0000000 --- a/include/Socket/Socket_Init.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "precomp.hpp" - -namespace Chattr { - -struct Socket_Init { -public: - Socket_Init(std::int32_t domain, std::int32_t type, std::int32_t protocol); - ~Socket_Init(); - - operator SOCKET() const; - - void bind(int __fd, const sockaddr *__addr, socklen_t __len); - - Socket_Init(const Socket_Init&) = delete; - Socket_Init& operator=(const Socket_Init&) = delete; -private: - bool valid_ = false; - SOCKET sock_ = INVALID_SOCKET; -}; - -} \ No newline at end of file diff --git a/include/precomp.hpp b/include/precomp.hpp index c330d5f..5b6a007 100644 --- a/include/precomp.hpp +++ b/include/precomp.hpp @@ -15,4 +15,5 @@ #error "이 플랫폼은 지원되지 않습니다." #endif -#include \ No newline at end of file +#include +#include "spdlog/spdlog.h" \ No newline at end of file