Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Checks: '
-fuchsia*,
-google-readability-todo,
-cppcoreguidelines-init-variables,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-pro-type-reinterpret-cast,
-llvm-namespace-comment,
-readability-implicit-bool-conversion,
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ on:
jobs:
build:
runs-on: ${{ matrix.os }}
permissions:
contents: read
actions: write

strategy:
# ensure we don't stop after 1 failure to always have a complete picture of what is failing
Expand Down Expand Up @@ -127,6 +130,9 @@ jobs:
needs: 'build'
runs-on: ubuntu-latest
if: always() && github.event_name == 'pull_request'
permissions:
contents: read
pull-requests: write

steps:
- name: Checkout Code
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/code_scanning.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
security-events: write
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v7

- name: flawfinder_scan
uses: david-a-wheeler/flawfinder@2.0.19
Expand Down Expand Up @@ -93,7 +93,7 @@ jobs:
- name: VCPKG Install (Windows)
uses: ./.github/workflows/windows-vcpkg
with:
key: ${{ runner.os }}-${{ env.config }}
key: vcpkg-cache-${{ runner.os }}

- name: Configure CMake
run: cmake -B ${{ env.build }} -DCMAKE_BUILD_TYPE=${{ env.config }}
Expand Down
22 changes: 0 additions & 22 deletions .github/workflows/download-cache.yml

This file was deleted.

4 changes: 1 addition & 3 deletions .github/workflows/windows-vcpkg/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,19 @@ runs:

- name: Fetch VCPKG Cache (Windows)
id: fetch-vcpkg-cache
if: runner.os == 'Windows'
uses: actions/cache/restore@v6
with:
key: ${{ inputs.key }}-vcpkg-${{ hashFiles('vcpkg.json') }}
path: ${{ env.VCPKG_CACHE }}

- name: VCPKG Install (Windows)
if: runner.os == 'Windows'
shell: powershell
run: |
echo "CMAKE_TOOLCHAIN_FILE=${env:VCPKG_ROOT}\scripts\buildsystems\vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append
vcpkg install

- name: Always Save VCPKG Cache (Windows)
if: always() && runner.os == 'Windows' && steps.fetch-vcpkg-cache.outputs.cache-hit != 'true'
if: always() && steps.fetch-vcpkg-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v6
with:
key: ${{ steps.fetch-vcpkg-cache.outputs.cache-primary-key }}
Expand Down
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
## Author Francois Michaut
##
## Started on Sun Aug 28 19:26:51 2022 Francois Michaut
## Last update Thu Jul 2 01:56:37 2026 Francois Michaut
## Last update Sat Oct 24 23:32:08 2026 Francois Michaut
##
## CMakeLists.txt : CMake to build the CppSockets library
##
Expand All @@ -21,6 +21,7 @@ project(LibCppSockets VERSION 0.1.0 LANGUAGES C CXX)
configure_file(include/CppSockets/Version.hpp.in include/CppSockets/Version.hpp)

add_library(cppsockets
source/Tls/Callbacks.cpp
source/Tls/Certificate.cpp
source/Tls/Context.cpp
source/Tls/Utils.cpp
Expand All @@ -40,7 +41,14 @@ target_include_directories(cppsockets
${PROJECT_SOURCE_DIR}/private
)

target_compile_definitions(cppsockets PRIVATE CPPSOCKETS_DLL_EXPORTS=1)
if(WIN32)
target_compile_definitions(cppsockets PRIVATE CPPSOCKETS_DLL_EXPORTS=1)
endif()

target_compile_options(cppsockets PRIVATE
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:-Wall -Wextra>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)

find_package(OpenSSL 3.0 COMPONENTS SSL)
target_link_libraries(cppsockets OpenSSL::SSL)
Expand Down
31 changes: 20 additions & 11 deletions include/CppSockets/Socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
** Author Francois Michaut
**
** Started on Sat Jan 15 01:17:42 2022 Francois Michaut
** Last update Wed Jul 1 14:20:12 2026 Francois Michaut
** Last update Sun Oct 25 11:38:13 2026 Francois Michaut
**
** Socket.hpp : Portable C++ socket class
*/
Expand Down Expand Up @@ -37,26 +37,27 @@ namespace CppSockets {
Socket();
Socket(int domain, int type, int protocol);
Socket(RawSocketType fd, bool connected);
~Socket();
virtual ~Socket();

// TODO Maybe enable copy with dup(2) ?
Socket(const Socket &other) = delete;
Socket(Socket &&other) noexcept;
auto operator=(const Socket &other) -> Socket & = delete;
auto operator=(Socket &&other) noexcept -> Socket &;

auto read(std::size_t len = -1) -> std::string;
auto read(char *buff, std::size_t size) -> std::size_t;
auto write(const std::string &buff) -> std::size_t;
auto write(const char *buff, std::size_t len) -> std::size_t;
virtual void close();

virtual auto read(std::size_t len = -1) -> std::string;
virtual auto read(char *buff, std::size_t size) -> std::size_t;
virtual auto write(std::string_view buff) -> std::size_t;
virtual auto write(const char *buff, std::size_t len) -> std::size_t;

auto set_reuseaddr(bool value) -> int;
auto getsockopt(int level, int optname, SockOptType *optval, socklen_t *optlen) -> int;
auto setsockopt(int level, int optname, const SockOptType *optval, socklen_t optlen) -> int;

void close();
auto connect(const IEndpoint &endpoint) -> int;
auto connect(const std::string &addr, uint16_t port) -> int;
virtual auto connect(const IEndpoint &endpoint) -> int;
virtual auto connect(const std::string &addr, uint16_t port) -> int;

auto bind(const IEndpoint &endpoint) -> int;
auto bind(const std::string &addr, uint16_t port) -> int;
Expand All @@ -74,15 +75,23 @@ namespace CppSockets {
[[nodiscard]] auto connected() const -> bool { return m_is_connected; }

static auto get_errno() -> int;
static auto strerror(int err) -> char *;
static auto strerror() -> char *;
static auto strerror(int err) -> std::string;
static auto strerror() -> std::string;

protected:
static void throw_errno_error(std::string message);
static void throw_errno_error(std::string message, int err);

static auto getsockopt(int fd, int level, int optname, SockOptType *optval, socklen_t *optlen) -> int;
static auto getsockopt(int fd, int level, int optname, SockOptType *optval, socklen_t optlen) -> int { return Socket::getsockopt(fd, level, optname, optval, &optlen); }

auto bind(std::uint32_t addr, uint16_t port) -> int;

void set_connected(bool status) { m_is_connected = status; };

void create_socket();

virtual auto acceptImpl(void *addr_out) -> Socket *;
private:
int m_domain = 0;
int m_type = 0;
Expand Down
7 changes: 2 additions & 5 deletions include/CppSockets/Tls/Context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
** Author Francois Michaut
**
** Started on Wed Aug 20 14:13:44 2025 Francois Michaut
** Last update Tue Jun 30 08:19:16 2026 Francois Michaut
** Last update Thu Oct 22 23:23:49 2026 Francois Michaut
**
** Context.hpp : Context for TLS sockets
*/
Expand All @@ -22,7 +22,7 @@ namespace CppSockets {
TlsContext(SSL_CTX_ptr ptr);
TlsContext(SSL_CTX *ptr, bool own = true);

TlsContext(const TlsContext &other) { *this = other; }
TlsContext(const TlsContext &other);
TlsContext(TlsContext &&other) noexcept;
auto operator=(const TlsContext &other) -> TlsContext &;
auto operator=(TlsContext &&other) noexcept -> TlsContext &;
Expand All @@ -41,8 +41,5 @@ namespace CppSockets {
private:
SSL_CTX_ptr m_ptr;
bool m_own = true;
TlsVerifyCallback m_verify_callback;

friend struct TlsContext_Accessor;
};
}
34 changes: 21 additions & 13 deletions include/CppSockets/Tls/Socket.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
** Author Francois Michaut
**
** Started on Wed Sep 14 20:51:23 2022 Francois Michaut
** Last update Fri Aug 22 21:55:50 2025 Francois Michaut
** Last update Sun Oct 25 12:00:59 2026 Francois Michaut
**
** SecureSocket.hpp : TLS socket wrapper using openssl
*/
Expand All @@ -20,30 +20,31 @@ namespace CppSockets {
// TODO add more TLS-related functions
class TlsSocket : public Socket {
public:
TlsSocket() = default;
// TODO: Constructor allowing application to reuse SSL_CTX objects
// (Maybe even a different TLS_CTX class to manage them ?)
TlsSocket() = default; // TODO: Null-init m_ssl, would segfault on any function call. Find a safer way.
TlsSocket(int domain, int type, int protocol, TlsContext ctx = {});
explicit TlsSocket(Socket &&other, TlsContext ctx = {});
explicit TlsSocket(Socket &&other, SSL_ptr ssl = nullptr);
explicit TlsSocket(RawSocketType fd, SSL_ptr ssl = nullptr);
~TlsSocket() noexcept;
~TlsSocket() noexcept override;

TlsSocket(const TlsSocket &other) = delete;
TlsSocket(TlsSocket &&other) noexcept;
auto operator=(const TlsSocket &other) -> TlsSocket & = delete;
auto operator=(TlsSocket &&other) noexcept -> TlsSocket &;

void close();
void close() override { this->close(false); };
bool close(bool force);

auto read(std::size_t len = -1) -> std::string;
auto read(char *buff, std::size_t size) -> std::size_t;
auto write(std::string_view buff) -> std::size_t { return this->write(buff.data(), buff.size()); };
auto write(const char *buff, std::size_t len) -> std::size_t;
// read() with no length reads until the peer closes; use read(N) when reading from untrusted peers
auto read(std::size_t len = -1) -> std::string override;
auto read(char *buff, std::size_t size) -> std::size_t override;
auto write(std::string_view buff) -> std::size_t override { return this->write(buff.data(), buff.size()); };
auto write(const char *buff, std::size_t len) -> std::size_t override;

void set_verify(int mode, SSL_verify_cb verify_callback = nullptr);
void set_verify(int mode, TlsVerifyCallback verify_callback = nullptr);
void set_verify_depth(int depth);
void set_certificate(const std::string &cert_path, const std::string &pkey_path);
auto connect(const IEndpoint &endpoint) -> int;
auto connect(const IEndpoint &endpoint) -> int override;

auto accept(void *addr_out, TlsContext ctx) -> std::unique_ptr<TlsSocket>;
auto accept(void *addr_out = nullptr) -> std::unique_ptr<TlsSocket> { return accept(addr_out, m_ctx); }
Expand All @@ -54,11 +55,18 @@ namespace CppSockets {
[[nodiscard]] auto get_peer_cert() const -> const X509_ptr & { return m_peer_cert; }

[[nodiscard]] auto tls_strerror(int ret) -> std::string;
protected:
auto acceptImpl(void *addr_out) -> TlsSocket * override { return acceptImpl(addr_out, m_ctx); };
auto acceptImpl(void *addr_out, TlsContext ctx) -> TlsSocket *;

void throw_tls_error(std::string message);
void throw_tls_error(std::string message, int ret);
private:
TlsContext m_ctx;
SSL_ptr m_ssl;
X509_ptr m_peer_cert;

void check_for_error(const std::string &error_msg, int ret);
bool m_should_shutdown = false;
void check_for_error(std::string error_msg, int ret);
};
}
2 changes: 1 addition & 1 deletion private/CppSockets/SslMacros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
** Author Francois Michaut
**
** Started on Wed Aug 20 16:54:02 2025 Francois Michaut
** Last update Thu Jul 2 03:01:00 2026 Francois Michaut
** Last update Thu Oct 22 22:48:57 2026 Francois Michaut
**
** SslMacros.hpp : Private Macros to define SSL wrappers
*/
Expand Down
9 changes: 8 additions & 1 deletion source/Address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
** Author Francois Michaut
**
** Started on Sun Feb 13 22:03:32 2022 Francois Michaut
** Last update Wed Jul 1 14:19:53 2026 Francois Michaut
** Last update Sun Oct 25 12:47:04 2026 Francois Michaut
**
** Address.cpp : Implementation of generic Address classes & functions
*/
Expand All @@ -28,6 +28,11 @@ namespace CppSockets {
auto IEndpoint::from_string(std::string endpoint) -> std::shared_ptr<CppSockets::IEndpoint> {
// TODO: Support IPv6
std::size_t colon_pos = endpoint.find_last_of(':');

if (colon_pos == std::string::npos) {
throw std::runtime_error("Invalid Endpoint");
}

std::stringstream ss{std::move(endpoint)};
std::string ip_part(colon_pos, '\0'); // 0-init str with enough size
std::uint16_t port = 0;
Expand All @@ -41,6 +46,8 @@ namespace CppSockets {
ss >> port;
}

// TODO: Error handling

return std::make_shared<EndpointV4>(ipv4, port);
}
}
Loading
Loading