diff --git a/.gitignore b/.gitignore index 1240b95..9e75863 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ build/ -libcppsockets.so +file-share +file-share-cli +*.so +*.dll +*.exe compile_commands.json *.tmp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5cd8fd3..3115408 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ ## Author Francois Michaut ## ## Started on Sun Aug 28 19:26:51 2022 Francois Michaut -## Last update Wed Aug 20 17:05:18 2025 Francois Michaut +## Last update Thu Jul 2 01:56:37 2026 Francois Michaut ## ## CMakeLists.txt : CMake to build the CppSockets library ## @@ -31,6 +31,7 @@ add_library(cppsockets source/Socket.cpp source/SocketInit.cpp ) + target_include_directories(cppsockets PUBLIC $ @@ -39,6 +40,8 @@ target_include_directories(cppsockets ${PROJECT_SOURCE_DIR}/private ) +target_compile_definitions(cppsockets PRIVATE CPPSOCKETS_DLL_EXPORTS=1) + find_package(OpenSSL 3.0 COMPONENTS SSL) target_link_libraries(cppsockets OpenSSL::SSL) if(WIN32) diff --git a/include/CppSockets/Address.hpp b/include/CppSockets/Address.hpp index 92d4837..4b77af4 100644 --- a/include/CppSockets/Address.hpp +++ b/include/CppSockets/Address.hpp @@ -1,10 +1,10 @@ /* -** Project CppSockets, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sun Feb 13 17:09:05 2022 Francois Michaut -** Last update Sat Jun 20 09:12:58 2026 Francois Michaut +** Last update Wed Jul 1 14:19:51 2026 Francois Michaut ** ** Address.hpp : Interface to represent network addresses */ diff --git a/include/CppSockets/IPv4.hpp b/include/CppSockets/IPv4.hpp index e169948..0a05349 100644 --- a/include/CppSockets/IPv4.hpp +++ b/include/CppSockets/IPv4.hpp @@ -1,10 +1,10 @@ /* -** Project CppSockets, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sun Feb 13 17:05:02 2022 Francois Michaut -** Last update Wed Aug 20 12:57:35 2025 Francois Michaut +** Last update Wed Jul 1 14:19:39 2026 Francois Michaut ** ** IPv4.hpp : Class used to represent and manipulate IPv4 addresses */ diff --git a/include/CppSockets/OSDetection.hpp b/include/CppSockets/OSDetection.hpp index 6463ae9..4b36951 100644 --- a/include/CppSockets/OSDetection.hpp +++ b/include/CppSockets/OSDetection.hpp @@ -1,10 +1,10 @@ /* -** Project CppSockets, 2023 +** Project LibCppSockets, 2023 ** ** Author Francois Michaut ** ** Started on Tue May 9 23:20:20 2023 Francois Michaut -** Last update Sun May 14 14:03:20 2023 Francois Michaut +** Last update Wed Jul 1 14:20:01 2026 Francois Michaut ** ** OSDetection.hpp : OS Detection macros */ @@ -12,15 +12,15 @@ #pragma once #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) - #define OS_WINDOWS + #define OS_WINDOWS 1 #elif defined (__APPLE__) - #define OS_UNIX - #define OS_APPLE + #define OS_UNIX 1 + #define OS_APPLE 1 #elif defined(__linux__) - #define OS_UNIX - #define OS_LINUX + #define OS_UNIX 1 + #define OS_LINUX 1 #elif defined(__unix__) - #define OS_UNIX + #define OS_UNIX 1 #else - #error "Unknown compiler, please open a issue or pull request to support your compiler" + #error "Unknown OS, please open a issue or pull request to support your OS" #endif diff --git a/include/CppSockets/Socket.hpp b/include/CppSockets/Socket.hpp index b6c6c5d..6b4bcc2 100644 --- a/include/CppSockets/Socket.hpp +++ b/include/CppSockets/Socket.hpp @@ -1,10 +1,10 @@ /* -** Project CppSockets, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sat Jan 15 01:17:42 2022 Francois Michaut -** Last update Wed Aug 20 14:01:21 2025 Francois Michaut +** Last update Wed Jul 1 14:20:12 2026 Francois Michaut ** ** Socket.hpp : Portable C++ socket class */ diff --git a/include/CppSockets/Tls/Certificate.hpp b/include/CppSockets/Tls/Certificate.hpp index 7303a43..aed44e1 100644 --- a/include/CppSockets/Tls/Certificate.hpp +++ b/include/CppSockets/Tls/Certificate.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Fri Aug 1 09:50:33 2025 Francois Michaut -** Last update Wed Aug 20 17:17:44 2025 Francois Michaut +** Last update Thu Jul 2 01:03:49 2026 Francois Michaut ** ** Certificate.hpp : Classes to create and manage Certificates */ @@ -27,6 +27,7 @@ namespace CppSockets { x509Name(); x509Name(X509_NAME_ptr ptr); x509Name(X509_NAME *ptr, bool own = true); + x509Name(const X509_NAME *ptr); x509Name(const x509Name &other) { *this = other; } x509Name(x509Name &&other) noexcept = default; @@ -73,6 +74,7 @@ namespace CppSockets { x509NameEntry(); x509NameEntry(X509_NAME_ENTRY_ptr ptr); x509NameEntry(X509_NAME_ENTRY *ptr, bool own = true); + x509NameEntry(const X509_NAME_ENTRY *ptr); x509NameEntry(const std::string &name, int type, const std::u8string &data); x509NameEntry(const ASN1_OBJECT *obj, int type, const std::u8string &data); x509NameEntry(int nid, int type, const std::u8string &data); @@ -103,6 +105,7 @@ namespace CppSockets { x509Extension(); x509Extension(X509_EXTENSION_ptr ptr); x509Extension(X509_EXTENSION *ptr, bool own = true); + x509Extension(const X509_EXTENSION *ptr); x509Extension(int nid, int crit, ASN1_OCTET_STRING *data); x509Extension(const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data); @@ -119,8 +122,8 @@ namespace CppSockets { void set_object(const ASN1_OBJECT *obj); void set_critical(bool crit); - [[nodiscard]] auto get_data() const -> ASN1_OCTET_STRING *; - [[nodiscard]] auto get_object() const -> ASN1_OBJECT *; + [[nodiscard]] auto get_data() const -> const ASN1_OCTET_STRING *; + [[nodiscard]] auto get_object() const -> const ASN1_OBJECT *; [[nodiscard]] auto get_critical() const -> bool; [[nodiscard]] auto get() const -> X509_EXTENSION * { return m_ptr.get(); } @@ -134,6 +137,7 @@ namespace CppSockets { x509Certificate(); x509Certificate(X509_ptr ptr); x509Certificate(X509 *ptr, bool own = true); + x509Certificate(const X509 *ptr); explicit x509Certificate(const std::filesystem::path &pem_file_path); x509Certificate(const x509Certificate &other) { *this = other; } diff --git a/include/CppSockets/Tls/Context.hpp b/include/CppSockets/Tls/Context.hpp index ece6978..f7b17f7 100644 --- a/include/CppSockets/Tls/Context.hpp +++ b/include/CppSockets/Tls/Context.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Wed Aug 20 14:13:44 2025 Francois Michaut -** Last update Fri Aug 22 21:43:02 2025 Francois Michaut +** Last update Tue Jun 30 08:19:16 2026 Francois Michaut ** ** Context.hpp : Context for TLS sockets */ diff --git a/include/CppSockets/Tls/Utils.hpp b/include/CppSockets/Tls/Utils.hpp index b73eaa4..94715ad 100644 --- a/include/CppSockets/Tls/Utils.hpp +++ b/include/CppSockets/Tls/Utils.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Fri Aug 1 09:54:53 2025 Francois Michaut -** Last update Wed Aug 20 16:49:57 2025 Francois Michaut +** Last update Wed Jul 1 19:48:56 2026 Francois Michaut ** ** Utils.hpp : Tls Utility types */ @@ -58,4 +58,5 @@ namespace CppSockets { // Don't leak macros #undef CPP_SOCKETS_TLS_UTILS_DEFINE_DTOR +#undef CPP_SOCKETS_TLS_UTILS_DEFINE_PTR_CMD_PREFIX #undef CPP_SOCKETS_TLS_UTILS_DEFINE_PTR diff --git a/include/CppSockets/Version.hpp.in b/include/CppSockets/Version.hpp.in index ba2e860..e4710df 100644 --- a/include/CppSockets/Version.hpp.in +++ b/include/CppSockets/Version.hpp.in @@ -1,10 +1,10 @@ /* -** Project CppSockets, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sun Aug 28 19:32:30 2022 Francois Michaut -** Last update Wed Sep 14 22:26:40 2022 Francois Michaut +** Last update Wed Jul 1 14:19:47 2026 Francois Michaut ** ** Version.hpp.in : Library version */ diff --git a/include/CppSockets/internal/DLLExport.hpp b/include/CppSockets/internal/DLLExport.hpp new file mode 100644 index 0000000..70f77ee --- /dev/null +++ b/include/CppSockets/internal/DLLExport.hpp @@ -0,0 +1,28 @@ +/* +** Project LibCppSockets, 2026 +** +** Author Francois Michaut +** +** Started on Wed Jul 1 12:30:17 2026 Francois Michaut +** Last update Wed Jul 1 18:54:43 2026 Francois Michaut +** +** DLLExport.hpp : Macros for DLL symbol exporting +*/ + +#pragma once + +#include "CppSockets/OSDetection.hpp" + +// TODO: Use theses to export only external symbols and avoid just exporting everything +#if OS_WINDOWS + #ifdef CPPSOCKETS_DLL_EXPORTS + // For windows, force the symbol to be exported when building the DLL + #define CPPSOCKETS_DLL_EXPORT __declspec(dllexport) + #else + // For windows, allows client code to know that the symbol must be loaded from the DLL + #define CPPSOCKETS_DLL_EXPORT __declspec(dllimport) + #endif +#else + // For Linux/MacOs force the symbol to be exported + #define CPPSOCKETS_DLL_EXPORT __attribute__ ((visibility("default"))) +#endif diff --git a/include/CppSockets/internal/SocketInit.hpp b/include/CppSockets/internal/SocketInit.hpp index fa30590..82eae29 100644 --- a/include/CppSockets/internal/SocketInit.hpp +++ b/include/CppSockets/internal/SocketInit.hpp @@ -1,23 +1,29 @@ /* -** Project CppSockets, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sat Jan 15 01:17:42 2022 Francois Michaut -** Last update Wed Aug 20 13:04:47 2025 Francois Michaut +** Last update Wed Jul 1 14:20:05 2026 Francois Michaut ** ** SocketInit.hpp : Socket class automatic initialization and teardown */ // Inspired from https://stackoverflow.com/questions/64753466/how-do-i-automatically-implicitly-create-a-instance-of-a-class-at-program-launch/64754436#64754436 +#pragma once + namespace CppSockets { class SocketInit { - struct Cleanup { - ~Cleanup(); - }; + public: + SocketInit(); + + private: + struct Cleanup { + ~Cleanup(); + }; - static bool init; - static Cleanup cleanup; + static const bool init; + static const Cleanup cleanup; }; } diff --git a/private/CppSockets/SslMacros.hpp b/private/CppSockets/SslMacros.hpp index cb0e3d7..d313c74 100644 --- a/private/CppSockets/SslMacros.hpp +++ b/private/CppSockets/SslMacros.hpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Wed Aug 20 16:54:02 2025 Francois Michaut -** Last update Fri Aug 22 21:46:55 2025 Francois Michaut +** Last update Thu Jul 2 03:01:00 2026 Francois Michaut ** ** SslMacros.hpp : Private Macros to define SSL wrappers */ @@ -12,17 +12,18 @@ #define REQUIRED_PTR(ptr, name) \ if (!ptr) { \ throw std::runtime_error("Failed to create " name); \ - } + } \ #define ASSIGNMENT_OPERATOR(type) \ if (this == &other) { \ return *this; \ } \ \ - type *dup = type##_dup(other.m_ptr.get()); \ + type *ptr = other.m_ptr.get(); \ + type *dup = type##_dup(ptr); \ \ - if (dup == nullptr) { \ - throw std::runtime_error("Failed to dup " #type); \ + if (ptr != nullptr && dup == nullptr) { \ + throw std::runtime_error("Failed to dup " #type); \ } \ if (!this->m_own) { \ (void)this->m_ptr.release(); \ @@ -36,11 +37,18 @@ return *this; \ } \ \ + type *ptr = other.m_ptr.get(); \ + \ + if (ptr) { \ + if (!SSL_CTX_up_ref(ptr)) { \ + throw std::runtime_error("Failed to up ref " #type); \ + } \ + } \ if (!this->m_own) { \ (void)this->m_ptr.release(); \ } \ - this->m_ptr.reset(other.m_ptr.get()); \ - this->m_own = false; \ + this->m_ptr.reset(ptr); \ + this->m_own = true; \ return *this; \ #define MAKE_DESTRUCTOR(klass) \ diff --git a/source/Address.cpp b/source/Address.cpp index a6d7207..388dd46 100644 --- a/source/Address.cpp +++ b/source/Address.cpp @@ -1,10 +1,10 @@ /* -** Project CppSocket, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sun Feb 13 22:03:32 2022 Francois Michaut -** Last update Sat Jun 20 09:13:40 2026 Francois Michaut +** Last update Wed Jul 1 14:19:53 2026 Francois Michaut ** ** Address.cpp : Implementation of generic Address classes & functions */ diff --git a/source/IPv4.cpp b/source/IPv4.cpp index b69f3d8..32900fc 100644 --- a/source/IPv4.cpp +++ b/source/IPv4.cpp @@ -1,10 +1,10 @@ /* -** Project CppSocket, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sun Feb 13 18:52:28 2022 Francois Michaut -** Last update Fri Jun 12 02:17:05 2026 Francois Michaut +** Last update Wed Jul 1 14:19:56 2026 Francois Michaut ** ** IPv4.cpp : Implementation of IPv4 class */ diff --git a/source/Socket.cpp b/source/Socket.cpp index 074d2e7..71b6de3 100644 --- a/source/Socket.cpp +++ b/source/Socket.cpp @@ -1,10 +1,10 @@ /* -** Project CppSocket, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Sat Jan 15 01:27:40 2022 Francois Michaut -** Last update Wed Aug 20 12:59:14 2025 Francois Michaut +** Last update Thu Jul 2 01:19:37 2026 Francois Michaut ** ** Socket.cpp : Protable C++ socket class implementation */ @@ -62,8 +62,9 @@ namespace CppSockets { Socket::Socket(int domain, int type, int protocol) : m_domain(domain), m_type(type), m_protocol(protocol), m_sockfd(::socket(domain, type, protocol)) { - if (m_sockfd == INVALID_SOCKET) + if (m_sockfd == INVALID_SOCKET) { throw std::runtime_error(std::string("Failed to create socket : ") + std::strerror(errno)); + } } Socket::~Socket() { diff --git a/source/SocketInit.cpp b/source/SocketInit.cpp index 1e88909..55e016d 100644 --- a/source/SocketInit.cpp +++ b/source/SocketInit.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Thu Sep 15 14:24:25 2022 Francois Michaut -** Last update Wed Aug 20 14:00:59 2025 Francois Michaut +** Last update Thu Jul 2 01:15:36 2026 Francois Michaut ** ** init.cpp : Startup/Cleanup functions implementation */ @@ -16,6 +16,9 @@ #include #ifdef OS_WINDOWS + #include + #include + #include #include #else @@ -23,15 +26,19 @@ #include #endif +static std::string init_error; + namespace CppSockets { - static bool init() { + static auto init() noexcept -> bool { #ifdef OS_WINDOWS WSADATA wsa_data; // TODO check value in wsa_data if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0) { // TODO: use WSAGetLastError - throw std::runtime_error(std::string("WASStartup Failed : ") + std::strerror(errno)); + init_error = std::string("WASStartup Failed : ") + std::strerror(errno); + std::cerr << init_error << '\n'; + return false; } #else // TODO check if all of this is needed (commented out because it should not) @@ -47,7 +54,7 @@ namespace CppSockets { #ifdef OS_WINDOWS if (WSACleanup() == SOCKET_ERROR) { // TODO use FormatMessage to get the error string - throw std::runtime_error(std::string("WSACleanup Failed : ") + std::to_string(WSAGetLastError())); + std::cerr << std::string("WSACleanup Failed : ") << std::to_string(WSAGetLastError()) << '\n'; } #else // TODO check return values / raise errors @@ -60,6 +67,12 @@ namespace CppSockets { deinit(); } - bool SocketInit::init = CppSockets::init(); - SocketInit::Cleanup SocketInit::cleanup; + const bool SocketInit::init = CppSockets::init(); + const SocketInit::Cleanup SocketInit::cleanup; + + SocketInit::SocketInit() { + if (!init) [[unlikely]] { + throw std::runtime_error(init_error); + } + } } diff --git a/source/Tls/Certificate.cpp b/source/Tls/Certificate.cpp index 9b32990..f0cbde7 100644 --- a/source/Tls/Certificate.cpp +++ b/source/Tls/Certificate.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Sat Aug 2 22:41:35 2025 Francois Michaut -** Last update Wed Aug 20 17:05:49 2025 Francois Michaut +** Last update Thu Jul 2 03:01:04 2026 Francois Michaut ** ** Certificate.cpp : Implementation of classes to create and manage Certificates */ @@ -51,6 +51,12 @@ namespace CppSockets { REQUIRED_PTR(m_ptr, "X509_NAME") } + x509Name::x509Name(const X509_NAME *ptr) : + m_ptr(const_cast(ptr)), m_own(false) + { + REQUIRED_PTR(m_ptr, "X509_NAME") + } + MAKE_DESTRUCTOR(x509Name) auto x509Name::operator=(const x509Name &other) -> x509Name & { @@ -86,9 +92,9 @@ namespace CppSockets { } auto x509Name::get_entry_by_index(int idx) const -> x509NameEntry { - X509_NAME_ENTRY *ptr{check_or_throw_openssl_error(X509_NAME_get_entry(m_ptr.get(), idx))}; + const X509_NAME_ENTRY *ptr{check_or_throw_openssl_error(X509_NAME_get_entry(m_ptr.get(), idx))}; - return {ptr, false}; + return {ptr}; } auto x509Name::get_entry(int nid, int lastpos) const -> x509NameEntry { @@ -138,6 +144,12 @@ namespace CppSockets { REQUIRED_PTR(m_ptr, "X509_NAME_ENTRY") } + x509NameEntry::x509NameEntry(const X509_NAME_ENTRY *ptr) : + m_ptr(const_cast(ptr)), m_own(false) + { + REQUIRED_PTR(m_ptr, "X509_NAME_ENTRY") + } + x509NameEntry::x509NameEntry(const std::string &name, int type, const std::u8string &data) : m_ptr(X509_NAME_ENTRY_create_by_txt(nullptr, name.c_str(), type, reinterpret_cast(data.c_str()), numeric_cast(data.size()))) { @@ -203,6 +215,12 @@ namespace CppSockets { REQUIRED_PTR(m_ptr, "X509_EXTENSION") } + x509Extension::x509Extension(const X509_EXTENSION *ptr) : + m_ptr(const_cast(ptr)), m_own(false) + { + REQUIRED_PTR(m_ptr, "X509_EXTENSION") + } + x509Extension::x509Extension(int nid, int crit, ASN1_OCTET_STRING *data) : m_ptr(X509_EXTENSION_create_by_NID(nullptr, nid, crit, data)) { @@ -233,11 +251,11 @@ namespace CppSockets { check_or_throw_openssl_error(X509_EXTENSION_set_critical(m_ptr.get(), crit)); } - auto x509Extension::get_data() const -> ASN1_OCTET_STRING * { + auto x509Extension::get_data() const -> const ASN1_OCTET_STRING * { return X509_EXTENSION_get_data(m_ptr.get()); } - auto x509Extension::get_object() const -> ASN1_OBJECT * { + auto x509Extension::get_object() const -> const ASN1_OBJECT * { return X509_EXTENSION_get_object(m_ptr.get()); } @@ -266,6 +284,12 @@ namespace CppSockets { REQUIRED_PTR(m_ptr, "X509") } + x509Certificate::x509Certificate(const X509 *ptr) : + m_ptr(const_cast(ptr)), m_own(false) + { + REQUIRED_PTR(m_ptr, "X509") + } + MAKE_DESTRUCTOR(x509Certificate) x509Certificate::x509Certificate(const std::filesystem::path &pem_file_path) { @@ -288,6 +312,7 @@ namespace CppSockets { throw std::runtime_error("Failed to load X509 Certificate"); } m_ptr.reset(x509); + m_own = true; } void x509Certificate::save(const std::filesystem::path &pem_file_path) const { @@ -318,11 +343,15 @@ namespace CppSockets { } auto x509Certificate::get_issuer_name() const -> x509Name { - return {X509_get_issuer_name(m_ptr.get()), false}; + const X509_NAME *ptr = X509_get_issuer_name(m_ptr.get()); + + return {ptr}; } auto x509Certificate::get_subject_name() const -> x509Name { - return {X509_get_subject_name(m_ptr.get()), false}; + const X509_NAME *ptr = X509_get_subject_name(m_ptr.get()); + + return {ptr}; } void x509Certificate::set_not_before(int offset_day, std::int64_t offset_sec, time_t *in_tm) { @@ -410,12 +439,12 @@ namespace CppSockets { } auto x509Certificate::get_extension(std::uint32_t loc) const -> x509Extension { - X509_EXTENSION *ptr {X509_get_ext(m_ptr.get(), numeric_cast(loc))}; + const X509_EXTENSION *ptr {X509_get_ext(m_ptr.get(), numeric_cast(loc))}; if (!ptr) { throw std::runtime_error("Failed to get extension"); } - return {ptr, false}; + return {ptr}; } auto x509Certificate::get_extension_by(int nid, int lastpos) const -> x509Extension { diff --git a/source/Tls/Context.cpp b/source/Tls/Context.cpp index bef0462..dae0432 100644 --- a/source/Tls/Context.cpp +++ b/source/Tls/Context.cpp @@ -4,7 +4,7 @@ ** Author Francois Michaut ** ** Started on Wed Aug 20 14:40:41 2025 Francois Michaut -** Last update Fri Aug 22 21:46:12 2025 Francois Michaut +** Last update Tue Jun 30 08:38:15 2026 Francois Michaut ** ** Context.cpp : Implementation of the Context for TLS sockets */ @@ -68,7 +68,8 @@ namespace CppSockets { } auto TlsContext::operator=(const TlsContext &other) -> TlsContext & { - UP_REF_ASSIGNMENT_OPERATOR(SSL_CTX) + UP_REF_ASSIGNMENT_OPERATOR(SSL_CTX); + m_verify_callback = other.m_verify_callback; } auto TlsContext::operator=(TlsContext &&other) noexcept -> TlsContext & { diff --git a/source/Tls/Socket.cpp b/source/Tls/Socket.cpp index da3ef8d..a1d0e5d 100644 --- a/source/Tls/Socket.cpp +++ b/source/Tls/Socket.cpp @@ -1,10 +1,10 @@ /* -** Project LibFileShareProtocol, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Wed Sep 14 21:04:42 2022 Francois Michaut -** Last update Fri Aug 22 21:57:23 2025 Francois Michaut +** Last update Wed Jul 1 14:20:15 2026 Francois Michaut ** ** SecureSocket.cpp : TLS socket wrapper implementation */ diff --git a/source/Tls/Utils.cpp b/source/Tls/Utils.cpp index de69f92..fc918d0 100644 --- a/source/Tls/Utils.cpp +++ b/source/Tls/Utils.cpp @@ -1,10 +1,10 @@ /* -** Project LibFileShareProtocol, 2025 +** Project LibCppSockets, 2025 ** ** Author Francois Michaut ** ** Started on Sun Aug 3 20:36:03 2025 Francois Michaut -** Last update Wed Aug 20 14:12:29 2025 Francois Michaut +** Last update Wed Jul 1 14:20:18 2026 Francois Michaut ** ** SSL_Utils.cpp : SSL Utility implementations */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 6d8e33e..1afea78 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,10 +1,10 @@ ## -## Project CppSockets-Tests, 2022 +## Project LibCppSockets, 2022 ## ## Author Francois Michaut ## ## Started on Mon Feb 14 19:35:41 2022 Francois Michaut -## Last update Fri Aug 22 21:12:37 2025 Francois Michaut +## Last update Wed Jul 1 19:27:57 2026 Francois Michaut ## ## CMakeLists.txt : CMake building and running tests for CppSockets ## @@ -13,6 +13,7 @@ include(CTest) create_test_sourcelist(TestFiles test_driver.cpp Tls/TestContext.cpp + Tls/TestOpensslWrappers.cpp TestSockets.cpp ) @@ -24,6 +25,11 @@ add_executable(unit_tests target_compile_definitions(unit_tests PRIVATE DEBUG) target_link_libraries(unit_tests cppsockets) +target_compile_options(unit_tests PRIVATE + $<$,$,$>:-UNDEBUG> + $<$:/UNDEBUG> +) + foreach (test ${TestFiles}) if (NOT ${test} MATCHES "test_driver.cpp$") get_filename_component (DName ${test} DIRECTORY) diff --git a/tests/TestSockets.cpp b/tests/TestSockets.cpp index c770050..61b1060 100644 --- a/tests/TestSockets.cpp +++ b/tests/TestSockets.cpp @@ -1,10 +1,10 @@ /* -** Project FileShare-Tests, 2022 +** Project LibCppSockets, 2022 ** ** Author Francois Michaut ** ** Started on Mon Feb 14 21:17:55 2022 Francois Michaut -** Last update Fri Aug 22 21:11:25 2025 Francois Michaut +** Last update Wed Jul 1 19:02:32 2026 Francois Michaut ** ** TestSockets.cpp : Socket tests */ @@ -13,12 +13,10 @@ #include "CppSockets/Socket.hpp" #ifndef OS_WINDOWS - -#include -#include -#include -#include - + #include + #include + #include + #include #endif using namespace CppSockets; @@ -49,20 +47,21 @@ auto TestSockets(int /* ac */, char ** const /* av */) -> int return 1; } waitpid(child, &ret, 0); - return !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0); // NOLINT(hicpp-signed-bitwise) - } else { - Socket soc(AF_INET, SOCK_STREAM, 0); - while (!soc.connected()) { - try { - soc.connect("127.0.0.1", port); - } catch (std::exception &e) { - std::cerr << "Got error: " << e.what() << std::endl; - } + bool exited_normally = WIFEXITED(ret) && WEXITSTATUS(ret) == 0; // NOLINT(hicpp-signed-bitwise) + return !exited_normally; + } + Socket soc(AF_INET, SOCK_STREAM, 0); + + while (!soc.connected()) { + try { + soc.connect("127.0.0.1", port); + } catch (std::exception &e) { + std::cerr << "Got error: " << e.what() << std::endl; } - std::cout << "Connected !" << std::endl; - soc.write(test); - return 0; } + std::cout << "Connected !" << std::endl; + soc.write(test); + return 0; #endif } diff --git a/tests/Tls/TestContext.cpp b/tests/Tls/TestContext.cpp index 86d8d5d..1ee94d7 100644 --- a/tests/Tls/TestContext.cpp +++ b/tests/Tls/TestContext.cpp @@ -1,10 +1,10 @@ /* -** Project FileShare-Tests, 2025 +** Project LibCppSockets, 2025 ** ** Author Francois Michaut ** ** Started on Fri Aug 22 21:09:12 2025 Francois Michaut -** Last update Fri Aug 22 21:36:06 2025 Francois Michaut +** Last update Wed Jul 1 14:21:42 2026 Francois Michaut ** ** TestContext.cpp : TlsContext tests */ diff --git a/tests/Tls/TestOpensslWrappers.cpp b/tests/Tls/TestOpensslWrappers.cpp new file mode 100644 index 0000000..c6357fe --- /dev/null +++ b/tests/Tls/TestOpensslWrappers.cpp @@ -0,0 +1,112 @@ +/* +** Project LibCppSockets, 2026 +** +** Author Francois Michaut +** +** Started on Wed Jul 1 14:14:07 2026 Francois Michaut +** Last update Thu Jul 2 03:00:44 2026 Francois Michaut +** +** TestOpensslWrappers.cpp : OpenSSL wrappers tests +*/ + +#include "CppSockets/Tls/Certificate.hpp" + +#include +#include +#include + +const std::u8string ORG_NAME = u8"test1"; +const std::u8string ORG_UNIT_NAME = u8"test2"; +const std::u8string USER_ID = u8"user_test"; +const std::u8string COMMON_NAME = u8"CommonName"; +const std::u8string DN_QUAL = u8"DN Qual"; + +void TestCertificateCreate(const std::filesystem::path &cert_path) { + CppSockets::EVP_PKEY_ptr pkey {EVP_RSA_gen(4096)}; // NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) + CppSockets::x509Certificate cert; + CppSockets::x509Name subject; + + cert.set_public_key(pkey); + + cert.set_not_before(0, 0); + cert.set_not_after(365, 0); + + // NOLINTBEGIN(hicpp-signed-bitwise) + subject.add_entry(NID_organizationName, MBSTRING_ASC, ORG_NAME); + subject.add_entry(NID_organizationalUnitName, MBSTRING_ASC, ORG_UNIT_NAME); + subject.add_entry(NID_userId, MBSTRING_ASC, USER_ID); + + subject.add_entry(NID_commonName, MBSTRING_ASC, COMMON_NAME); + subject.add_entry(NID_dnQualifier, MBSTRING_ASC, DN_QUAL); + // NOLINTEND(hicpp-signed-bitwise) + + cert.set_self_signed_name(subject); + cert.sign(pkey); + + cert.save(cert_path); +} + +void TestCertificateLoad(const std::filesystem::path &cert_path) { + CppSockets::x509Certificate cert; + + cert.load(cert_path); + CppSockets::x509Name subject = cert.get_subject_name(); + CppSockets::x509NameEntry org_name = subject.get_entry(NID_organizationName); + CppSockets::x509NameEntry org_unit_name = subject.get_entry(NID_organizationalUnitName); + CppSockets::x509NameEntry user_id = subject.get_entry(NID_userId); + CppSockets::x509NameEntry common_name = subject.get_entry(NID_commonName); + CppSockets::x509NameEntry dn_qual = subject.get_entry(NID_dnQualifier); + + const ASN1_STRING *org_name_str = org_name.get_data(); + const ASN1_STRING *org_unit_name_str = org_unit_name.get_data(); + const ASN1_STRING *user_id_str = user_id.get_data(); + const ASN1_STRING *common_name_str = common_name.get_data(); + const ASN1_STRING *dn_qual_str = dn_qual.get_data(); + + const auto *org_name_data = reinterpret_cast( + ASN1_STRING_get0_data(org_name_str) + ); + const auto *org_unit_name_data = reinterpret_cast( + ASN1_STRING_get0_data(org_unit_name_str) + ); + const auto *user_id_data = reinterpret_cast( + ASN1_STRING_get0_data(user_id_str) + ); + const auto *common_name_data = reinterpret_cast( + ASN1_STRING_get0_data(common_name_str) + ); + const auto *dn_qual_data = reinterpret_cast( + ASN1_STRING_get0_data(dn_qual_str) + ); + + std::basic_string_view org_name_view { + org_name_data, static_cast(ASN1_STRING_length(org_name_str)) + }; + std::basic_string_view org_unit_name_view { + org_unit_name_data, static_cast(ASN1_STRING_length(org_unit_name_str)) + }; + std::basic_string_view user_id_view { + user_id_data, static_cast(ASN1_STRING_length(user_id_str)) + }; + std::basic_string_view common_name_view { + common_name_data, static_cast(ASN1_STRING_length(common_name_str)) + }; + std::basic_string_view dn_qual_view { + dn_qual_data, static_cast(ASN1_STRING_length(dn_qual_str)) + }; + + assert(ORG_NAME == org_name_view); + assert(ORG_UNIT_NAME == org_unit_name_view); + assert(USER_ID == user_id_view); + assert(COMMON_NAME == common_name_view); + assert(DN_QUAL == dn_qual_view); +} + +auto Tls_TestOpensslWrappers(int /* ac */, char ** const /* argv */) -> int { + std::filesystem::path cert_path = std::filesystem::temp_directory_path() / "test_cppsockets___random_file_name"; + + TestCertificateCreate(cert_path); + TestCertificateLoad(cert_path); + std::filesystem::remove(cert_path); + return 0; +}