Skip to content

Commit 75d5bad

Browse files
committed
More bugfixes & improvements
- Removed ambiguity around IPv4 byte order - Socket::accept now supports out addr param - TlsSocket now supports setting peer hostname - Fixed Windows error handling with new unified constants - Improved IEndpoint parsing - Clearly document that IPv6 isn't yet supported with specific errors - Better socket re-use / reconnect (specially for TlsSocket) - Improve non-blocking socket support (including TlsSocket::accept) - Properly fix TlsCallbackData cleanup - dup const Tls objects and take ownership for better const correctness - Safer security defaults on TlsContext
1 parent a9c59b9 commit 75d5bad

27 files changed

Lines changed: 559 additions & 239 deletions

‎.clang-tidy‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Checks: '
66
-fuchsia*,
77
-google-readability-todo,
88
-cppcoreguidelines-init-variables,
9+
-cppcoreguidelines-avoid-do-while,
910
-cppcoreguidelines-owning-memory,
1011
-cppcoreguidelines-pro-type-reinterpret-cast,
1112
-llvm-namespace-comment,
@@ -27,7 +28,7 @@ FormatStyle: 'none' # TODO: Replace with 'file' once we have a proper .clang-for
2728
InheritParentConfig: true
2829
CheckOptions:
2930
misc-include-cleaner.MissingIncludes: 'false'
30-
misc-include-cleaner.IgnoreHeaders: 'CppSockets/OSDetection.*'
31+
misc-include-cleaner.IgnoreHeaders: 'CppSockets/OSDetection\.hpp;CppSockets/SocketInternals\.hpp'
3132

3233
bugprone-argument-comment.StrictMode: 1
3334

‎CMakeLists.txt‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
## Author Francois Michaut
55
##
66
## Started on Sun Aug 28 19:26:51 2022 Francois Michaut
7-
## Last update Sat Oct 24 23:32:08 2026 Francois Michaut
7+
## Last update Mon Oct 26 11:56:28 2026 Francois Michaut
88
##
99
## CMakeLists.txt : CMake to build the CppSockets library
1010
##
@@ -42,7 +42,7 @@ target_include_directories(cppsockets
4242
)
4343

4444
if(WIN32)
45-
target_compile_definitions(cppsockets PRIVATE CPPSOCKETS_DLL_EXPORTS=1)
45+
target_compile_definitions(cppsockets PRIVATE CPPSOCKETS_DLL_EXPORTS=1 NOMINMAX)
4646
endif()
4747

4848
target_compile_options(cppsockets PRIVATE

‎include/CppSockets/Address.hpp‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
** Author Francois Michaut
55
**
66
** Started on Sun Feb 13 17:09:05 2022 Francois Michaut
7-
** Last update Wed Jul 1 14:19:51 2026 Francois Michaut
7+
** Last update Mon Oct 26 12:13:43 2026 Francois Michaut
88
**
99
** Address.hpp : Interface to represent network addresses
1010
*/
@@ -36,9 +36,7 @@ namespace CppSockets {
3636
[[nodiscard]] virtual auto get_addr() const -> const IAddress & = 0;
3737
[[nodiscard]] virtual auto to_string() const -> const std::string & = 0;
3838

39-
static auto from_string(std::string endpoint) -> std::shared_ptr<CppSockets::IEndpoint>;
4039
static auto from_string(std::string_view endpoint) -> std::shared_ptr<CppSockets::IEndpoint>;
41-
4240
protected:
4341
[[nodiscard]] auto make_string() const -> std::string;
4442
};

‎include/CppSockets/IPv4.hpp‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
** Author Francois Michaut
55
**
66
** Started on Sun Feb 13 17:05:02 2022 Francois Michaut
7-
** Last update Wed Jul 1 14:19:39 2026 Francois Michaut
7+
** Last update Mon Oct 26 14:26:38 2026 Francois Michaut
88
**
99
** IPv4.hpp : Class used to represent and manipulate IPv4 addresses
1010
*/
@@ -13,18 +13,25 @@
1313

1414
#include "CppSockets/Address.hpp"
1515

16+
#include <string_view>
17+
1618
namespace CppSockets {
1719
class IPv4 : public IAddress {
1820
public:
19-
explicit IPv4(std::uint32_t addr);
20-
IPv4(const char *addr); // TODO add support for string. Maybe string_view ?
21+
IPv4(std::string_view addr);
22+
23+
static auto from_host_order(std::uint32_t addr) -> IPv4;
24+
static auto from_network_order(std::uint32_t addr) -> IPv4;
2125

26+
// returns address in network byte order
2227
[[nodiscard]] auto get_address() const -> std::uint32_t override;
2328
[[nodiscard]] auto get_family() const -> int override;
2429
[[nodiscard]] auto to_string() const -> const std::string & override;
2530

2631
private:
27-
std::uint32_t addr;
32+
IPv4(std::uint32_t addr);
33+
34+
std::uint32_t addr; // always network byte order
2835
std::string str;
2936
};
3037
using EndpointV4 = Endpoint<IPv4>;

‎include/CppSockets/OSDetection.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
** Author Francois Michaut
55
**
66
** Started on Tue May 9 23:20:20 2023 Francois Michaut
7-
** Last update Wed Jul 1 14:20:01 2026 Francois Michaut
7+
** Last update Sun Oct 25 23:15:10 2026 Francois Michaut
88
**
99
** OSDetection.hpp : OS Detection macros
1010
*/

‎include/CppSockets/PollEvent.hpp‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
** Project LibCppSockets, 2022
3+
**
4+
** Author Francois Michaut
5+
**
6+
** Started on Mon Oct 26 09:37:12 2026 Francois Michaut
7+
** Last update Mon Oct 26 09:48:55 2026 Francois Michaut
8+
**
9+
** PollEvent.hpp : Helper enum for Socket::poll()
10+
*/
11+
12+
#pragma once
13+
14+
#include <cstdint>
15+
16+
namespace CppSockets {
17+
class PollEvent {
18+
public:
19+
enum Value : std::uint8_t {
20+
NONE = 0,
21+
READ = 1,
22+
WRITE = 2,
23+
};
24+
25+
constexpr PollEvent() : m_value(Value::NONE) {}
26+
constexpr PollEvent(Value value) : m_value(value) {}
27+
28+
constexpr auto operator|=(PollEvent other) -> PollEvent & {
29+
m_value = static_cast<Value>(to_uint(m_value) | to_uint(other.m_value));
30+
return *this;
31+
}
32+
constexpr auto operator&=(PollEvent other) -> PollEvent & {
33+
m_value = static_cast<Value>(to_uint(m_value) & to_uint(other.m_value));
34+
return *this;
35+
}
36+
[[nodiscard]] constexpr auto operator|(PollEvent other) const -> PollEvent {
37+
other |= *this;
38+
return other;
39+
}
40+
[[nodiscard]] constexpr auto operator&(PollEvent other) const -> PollEvent {
41+
other &= *this;
42+
return other;
43+
}
44+
[[nodiscard]] constexpr auto operator==(PollEvent other) const -> bool { return m_value == other.m_value; }
45+
[[nodiscard]] constexpr auto operator!=(PollEvent other) const -> bool { return m_value != other.m_value; }
46+
47+
explicit constexpr operator bool() const { return m_value != Value::NONE; }
48+
49+
[[nodiscard]] constexpr auto has(PollEvent event) const -> bool {
50+
return (to_uint(m_value) & to_uint(event.m_value)) != 0;
51+
}
52+
[[nodiscard]] constexpr auto value() const -> Value { return m_value; }
53+
54+
private:
55+
static constexpr auto to_uint(Value value) -> std::uint8_t {
56+
return static_cast<std::uint8_t>(value);
57+
}
58+
59+
Value m_value;
60+
};
61+
}

‎include/CppSockets/Socket.hpp‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,35 @@
44
** Author Francois Michaut
55
**
66
** Started on Sat Jan 15 01:17:42 2022 Francois Michaut
7-
** Last update Sun Oct 25 11:38:13 2026 Francois Michaut
7+
** Last update Mon Oct 26 20:22:18 2026 Francois Michaut
88
**
99
** Socket.hpp : Portable C++ socket class
1010
*/
1111

1212
#pragma once
1313

14+
#include "CppSockets/Address.hpp"
1415
#include "CppSockets/OSDetection.hpp"
15-
#include "CppSockets/internal/SocketInit.hpp"
16+
#include "CppSockets/PollEvent.hpp"
1617

1718
// TODO: move the RawSocketType in CppSockets namespace
1819
#ifdef OS_WINDOWS
19-
#define NOMINMAX
2020
#include <winsock2.h>
2121
using RawSocketType=SOCKET;
2222
using socklen_t=int;
2323
using SockOptType=char;
24+
using PollfdType=WSAPOLLFD;
2425
#else
2526
#include <sys/socket.h>
2627
using RawSocketType=int;
2728
using SockOptType=void;
29+
using PollfdType=struct pollfd;
2830
#endif
2931

32+
#include <cstdint>
3033
#include <memory>
3134

32-
#include "CppSockets/Address.hpp"
35+
#include "CppSockets/internal/SocketInit.hpp"
3336

3437
namespace CppSockets {
3538
class Socket : SocketInit {
@@ -47,9 +50,12 @@ namespace CppSockets {
4750

4851
virtual void close();
4952

50-
virtual auto read(std::size_t len = -1) -> std::string;
53+
// TODO: Add support for writev/WSASend and sendfile/WSATransmitPackets
54+
55+
// read() with no lenght blocks once then returns all currently available data
56+
auto read(std::size_t len = -1) -> std::string;
5157
virtual auto read(char *buff, std::size_t size) -> std::size_t;
52-
virtual auto write(std::string_view buff) -> std::size_t;
58+
auto write(std::string_view buff) -> std::size_t { return this->write(buff.data(), buff.size()); };
5359
virtual auto write(const char *buff, std::size_t len) -> std::size_t;
5460

5561
auto set_reuseaddr(bool value) -> int;
@@ -62,7 +68,11 @@ namespace CppSockets {
6268
auto bind(const IEndpoint &endpoint) -> int;
6369
auto bind(const std::string &addr, uint16_t port) -> int;
6470
auto listen(int backlog) -> int;
65-
auto accept(void *addr_out = nullptr) -> std::unique_ptr<Socket>;
71+
72+
auto accept() -> std::unique_ptr<Socket>;
73+
auto accept(sockaddr_storage &addr) -> std::unique_ptr<Socket>;
74+
75+
[[nodiscard]] auto poll(PollEvent events, int timeout_ms = 0) const -> PollEvent;
6676

6777
void set_blocking(bool val);
6878

@@ -91,7 +101,8 @@ namespace CppSockets {
91101

92102
void create_socket();
93103

94-
virtual auto acceptImpl(void *addr_out) -> Socket *;
104+
[[nodiscard]] virtual auto has_more_data() const -> bool;
105+
virtual auto acceptImpl(sockaddr_storage *addr_out) -> Socket *;
95106
private:
96107
int m_domain = 0;
97108
int m_type = 0;

‎include/CppSockets/Tls/Certificate.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
** Author Francois Michaut
55
**
66
** Started on Fri Aug 1 09:50:33 2025 Francois Michaut
7-
** Last update Thu Jul 2 01:03:49 2026 Francois Michaut
7+
** Last update Sun Oct 25 23:16:01 2026 Francois Michaut
88
**
99
** Certificate.hpp : Classes to create and manage Certificates
1010
*/

‎include/CppSockets/Tls/Context.hpp‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ namespace CppSockets {
3030
~TlsContext();
3131

3232
void set_min_proto_version(int version);
33+
void set_cipher_list(const char *cipher_list);
34+
void set_ciphersuites(const char *ciphersuites);
3335

3436
void set_verify(int mode, TlsVerifyCallback callback = {});
3537
void set_verify_depth(int depth);

‎include/CppSockets/Tls/Socket.hpp‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
** Author Francois Michaut
55
**
66
** Started on Wed Sep 14 20:51:23 2022 Francois Michaut
7-
** Last update Sun Oct 25 12:00:59 2026 Francois Michaut
7+
** Last update Mon Oct 26 21:37:23 2026 Francois Michaut
88
**
99
** SecureSocket.hpp : TLS socket wrapper using openssl
1010
*/
@@ -35,29 +35,36 @@ namespace CppSockets {
3535
void close() override { this->close(false); };
3636
bool close(bool force);
3737

38-
// read() with no length reads until the peer closes; use read(N) when reading from untrusted peers
39-
auto read(std::size_t len = -1) -> std::string override;
38+
// TODO: Add support for SSL_sendfile + SNI / ALPN
4039
auto read(char *buff, std::size_t size) -> std::size_t override;
41-
auto write(std::string_view buff) -> std::size_t override { return this->write(buff.data(), buff.size()); };
4240
auto write(const char *buff, std::size_t len) -> std::size_t override;
4341

4442
void set_verify(int mode, TlsVerifyCallback verify_callback = nullptr);
4543
void set_verify_depth(int depth);
4644
void set_certificate(const std::string &cert_path, const std::string &pkey_path);
45+
// Must be called before connect() for hostname verification to take
46+
// effect (requires peer verification to be enabled).
47+
void set_hostname(const std::string &hostname) { set_hostname(hostname.c_str()); }
48+
void set_hostname(const char *hostname);
49+
50+
// TODO: Add connect overload that take a string hostname and port and call set_hostname automatically
4751
auto connect(const IEndpoint &endpoint) -> int override;
4852

49-
auto accept(void *addr_out, TlsContext ctx) -> std::unique_ptr<TlsSocket>;
50-
auto accept(void *addr_out = nullptr) -> std::unique_ptr<TlsSocket> { return accept(addr_out, m_ctx); }
51-
auto accept(TlsContext ctx) -> std::unique_ptr<TlsSocket> { return accept(nullptr, std::move(ctx)); }
53+
auto accept() -> std::unique_ptr<TlsSocket> { return accept(m_ctx); }
54+
auto accept(TlsContext ctx) -> std::unique_ptr<TlsSocket>;
55+
auto accept(sockaddr_storage &addr) -> std::unique_ptr<TlsSocket> { return accept(addr, m_ctx); }
56+
auto accept(sockaddr_storage &addr, TlsContext ctx) -> std::unique_ptr<TlsSocket>;
5257

5358
[[nodiscard]] auto get_ssl_ctx() const -> TlsContext;
5459
[[nodiscard]] auto get_ssl() const -> const SSL_ptr & { return m_ssl; }
5560
[[nodiscard]] auto get_peer_cert() const -> const X509_ptr & { return m_peer_cert; }
5661

57-
[[nodiscard]] auto tls_strerror(int ret) -> std::string;
62+
[[nodiscard]] auto tls_errno(int ret) -> int;
5863
protected:
59-
auto acceptImpl(void *addr_out) -> TlsSocket * override { return acceptImpl(addr_out, m_ctx); };
60-
auto acceptImpl(void *addr_out, TlsContext ctx) -> TlsSocket *;
64+
auto acceptImpl(sockaddr_storage *addr_out) -> TlsSocket * override { return acceptImpl(addr_out, m_ctx); };
65+
auto acceptImpl(sockaddr_storage *addr_out, TlsContext ctx) -> TlsSocket *;
66+
67+
[[nodiscard]] auto has_more_data() const -> bool override;
6168

6269
void throw_tls_error(std::string message);
6370
void throw_tls_error(std::string message, int ret);
@@ -67,6 +74,7 @@ namespace CppSockets {
6774
X509_ptr m_peer_cert;
6875

6976
bool m_should_shutdown = false;
70-
void check_for_error(std::string error_msg, int ret);
77+
std::unique_ptr<TlsSocket> m_pending_accept; // partially handshaken accepted socket, for non-blocking sockets
78+
auto handle_ssl_io_result(std::string error_msg, int ssl_ret, std::size_t nb) -> std::size_t;
7179
};
7280
}

0 commit comments

Comments
 (0)