Skip to content

Commit 8827713

Browse files
authored
Added set_ipv6_v6only method (#1905)
* Added `set_ipv6_v6only` method * Adjust the place where socket_options is called
1 parent 6cdd349 commit 8827713

File tree

2 files changed

+54
-33
lines changed

2 files changed

+54
-33
lines changed

httplib.h

+53-32
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@
9090
#define CPPHTTPLIB_TCP_NODELAY false
9191
#endif
9292

93+
#ifndef CPPHTTPLIB_IPV6_V6ONLY
94+
#define CPPHTTPLIB_IPV6_V6ONLY false
95+
#endif
96+
9397
#ifndef CPPHTTPLIB_RECV_BUFSIZ
9498
#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
9599
#endif
@@ -900,6 +904,7 @@ class Server {
900904

901905
Server &set_address_family(int family);
902906
Server &set_tcp_nodelay(bool on);
907+
Server &set_ipv6_v6only(bool on);
903908
Server &set_socket_options(SocketOptions socket_options);
904909

905910
Server &set_default_headers(Headers headers);
@@ -1040,6 +1045,7 @@ class Server {
10401045

10411046
int address_family_ = AF_UNSPEC;
10421047
bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
1048+
bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;
10431049
SocketOptions socket_options_ = default_socket_options;
10441050

10451051
Headers default_headers_;
@@ -1322,6 +1328,7 @@ class ClientImpl {
13221328

13231329
void set_address_family(int family);
13241330
void set_tcp_nodelay(bool on);
1331+
void set_ipv6_v6only(bool on);
13251332
void set_socket_options(SocketOptions socket_options);
13261333

13271334
void set_connection_timeout(time_t sec, time_t usec = 0);
@@ -1459,6 +1466,7 @@ class ClientImpl {
14591466

14601467
int address_family_ = AF_UNSPEC;
14611468
bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
1469+
bool ipv6_v6only_ = CPPHTTPLIB_IPV6_V6ONLY;
14621470
SocketOptions socket_options_ = nullptr;
14631471

14641472
bool compress_ = false;
@@ -1968,19 +1976,19 @@ inline ssize_t Stream::write_format(const char *fmt, const Args &...args) {
19681976
}
19691977

19701978
inline void default_socket_options(socket_t sock) {
1971-
int yes = 1;
1979+
int opt = 1;
19721980
#ifdef _WIN32
19731981
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1974-
reinterpret_cast<const char *>(&yes), sizeof(yes));
1982+
reinterpret_cast<const char *>(&opt), sizeof(opt));
19751983
setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
1976-
reinterpret_cast<const char *>(&yes), sizeof(yes));
1984+
reinterpret_cast<const char *>(&opt), sizeof(opt));
19771985
#else
19781986
#ifdef SO_REUSEPORT
19791987
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
1980-
reinterpret_cast<const void *>(&yes), sizeof(yes));
1988+
reinterpret_cast<const void *>(&opt), sizeof(opt));
19811989
#else
19821990
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
1983-
reinterpret_cast<const void *>(&yes), sizeof(yes));
1991+
reinterpret_cast<const void *>(&opt), sizeof(opt));
19841992
#endif
19851993
#endif
19861994
}
@@ -2219,12 +2227,15 @@ bool process_client_socket(socket_t sock, time_t read_timeout_sec,
22192227
time_t write_timeout_usec,
22202228
std::function<bool(Stream &)> callback);
22212229

2222-
socket_t create_client_socket(
2223-
const std::string &host, const std::string &ip, int port,
2224-
int address_family, bool tcp_nodelay, SocketOptions socket_options,
2225-
time_t connection_timeout_sec, time_t connection_timeout_usec,
2226-
time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
2227-
time_t write_timeout_usec, const std::string &intf, Error &error);
2230+
socket_t create_client_socket(const std::string &host, const std::string &ip,
2231+
int port, int address_family, bool tcp_nodelay,
2232+
bool ipv6_v6only, SocketOptions socket_options,
2233+
time_t connection_timeout_sec,
2234+
time_t connection_timeout_usec,
2235+
time_t read_timeout_sec, time_t read_timeout_usec,
2236+
time_t write_timeout_sec,
2237+
time_t write_timeout_usec,
2238+
const std::string &intf, Error &error);
22282239

22292240
const char *get_header_value(const Headers &headers, const std::string &key,
22302241
const char *def, size_t id);
@@ -3239,7 +3250,7 @@ inline int shutdown_socket(socket_t sock) {
32393250
template <typename BindOrConnect>
32403251
socket_t create_socket(const std::string &host, const std::string &ip, int port,
32413252
int address_family, int socket_flags, bool tcp_nodelay,
3242-
SocketOptions socket_options,
3253+
bool ipv6_v6only, SocketOptions socket_options,
32433254
BindOrConnect bind_or_connect) {
32443255
// Get address info
32453256
const char *node = nullptr;
@@ -3350,29 +3361,29 @@ socket_t create_socket(const std::string &host, const std::string &ip, int port,
33503361
#endif
33513362

33523363
if (tcp_nodelay) {
3353-
auto yes = 1;
3364+
auto opt = 1;
33543365
#ifdef _WIN32
33553366
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
3356-
reinterpret_cast<const char *>(&yes), sizeof(yes));
3367+
reinterpret_cast<const char *>(&opt), sizeof(opt));
33573368
#else
33583369
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
3359-
reinterpret_cast<const void *>(&yes), sizeof(yes));
3370+
reinterpret_cast<const void *>(&opt), sizeof(opt));
33603371
#endif
33613372
}
33623373

3363-
if (socket_options) { socket_options(sock); }
3364-
33653374
if (rp->ai_family == AF_INET6) {
3366-
auto no = 0;
3375+
auto opt = ipv6_v6only ? 1 : 0;
33673376
#ifdef _WIN32
33683377
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
3369-
reinterpret_cast<const char *>(&no), sizeof(no));
3378+
reinterpret_cast<const char *>(&opt), sizeof(opt));
33703379
#else
33713380
setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
3372-
reinterpret_cast<const void *>(&no), sizeof(no));
3381+
reinterpret_cast<const void *>(&opt), sizeof(opt));
33733382
#endif
33743383
}
33753384

3385+
if (socket_options) { socket_options(sock); }
3386+
33763387
// bind or connect
33773388
auto quit = false;
33783389
if (bind_or_connect(sock, *rp, quit)) {
@@ -3477,12 +3488,14 @@ inline std::string if2ip(int address_family, const std::string &ifn) {
34773488

34783489
inline socket_t create_client_socket(
34793490
const std::string &host, const std::string &ip, int port,
3480-
int address_family, bool tcp_nodelay, SocketOptions socket_options,
3481-
time_t connection_timeout_sec, time_t connection_timeout_usec,
3482-
time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
3491+
int address_family, bool tcp_nodelay, bool ipv6_v6only,
3492+
SocketOptions socket_options, time_t connection_timeout_sec,
3493+
time_t connection_timeout_usec, time_t read_timeout_sec,
3494+
time_t read_timeout_usec, time_t write_timeout_sec,
34833495
time_t write_timeout_usec, const std::string &intf, Error &error) {
34843496
auto sock = create_socket(
3485-
host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options),
3497+
host, ip, port, address_family, 0, tcp_nodelay, ipv6_v6only,
3498+
std::move(socket_options),
34863499
[&](socket_t sock2, struct addrinfo &ai, bool &quit) -> bool {
34873500
if (!intf.empty()) {
34883501
#ifdef USE_IF2IP
@@ -6061,6 +6074,11 @@ inline Server &Server::set_tcp_nodelay(bool on) {
60616074
return *this;
60626075
}
60636076

6077+
inline Server &Server::set_ipv6_v6only(bool on) {
6078+
ipv6_v6only_ = on;
6079+
return *this;
6080+
}
6081+
60646082
inline Server &Server::set_socket_options(SocketOptions socket_options) {
60656083
socket_options_ = std::move(socket_options);
60666084
return *this;
@@ -6491,7 +6509,7 @@ Server::create_server_socket(const std::string &host, int port,
64916509
SocketOptions socket_options) const {
64926510
return detail::create_socket(
64936511
host, std::string(), port, address_family_, socket_flags, tcp_nodelay_,
6494-
std::move(socket_options),
6512+
ipv6_v6only_, std::move(socket_options),
64956513
[](socket_t sock, struct addrinfo &ai, bool & /*quit*/) -> bool {
64966514
if (::bind(sock, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen))) {
64976515
return false;
@@ -7041,6 +7059,7 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) {
70417059
url_encode_ = rhs.url_encode_;
70427060
address_family_ = rhs.address_family_;
70437061
tcp_nodelay_ = rhs.tcp_nodelay_;
7062+
ipv6_v6only_ = rhs.ipv6_v6only_;
70447063
socket_options_ = rhs.socket_options_;
70457064
compress_ = rhs.compress_;
70467065
decompress_ = rhs.decompress_;
@@ -7069,9 +7088,9 @@ inline socket_t ClientImpl::create_client_socket(Error &error) const {
70697088
if (!proxy_host_.empty() && proxy_port_ != -1) {
70707089
return detail::create_client_socket(
70717090
proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_,
7072-
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
7073-
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
7074-
write_timeout_usec_, interface_, error);
7091+
ipv6_v6only_, socket_options_, connection_timeout_sec_,
7092+
connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_,
7093+
write_timeout_sec_, write_timeout_usec_, interface_, error);
70757094
}
70767095

70777096
// Check is custom IP specified for host_
@@ -7080,10 +7099,10 @@ inline socket_t ClientImpl::create_client_socket(Error &error) const {
70807099
if (it != addr_map_.end()) { ip = it->second; }
70817100

70827101
return detail::create_client_socket(
7083-
host_, ip, port_, address_family_, tcp_nodelay_, socket_options_,
7084-
connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_,
7085-
read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_,
7086-
error);
7102+
host_, ip, port_, address_family_, tcp_nodelay_, ipv6_v6only_,
7103+
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
7104+
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
7105+
write_timeout_usec_, interface_, error);
70877106
}
70887107

70897108
inline bool ClientImpl::create_and_connect_socket(Socket &socket,
@@ -8487,6 +8506,8 @@ inline void ClientImpl::set_address_family(int family) {
84878506

84888507
inline void ClientImpl::set_tcp_nodelay(bool on) { tcp_nodelay_ = on; }
84898508

8509+
inline void ClientImpl::set_ipv6_v6only(bool on) { ipv6_v6only_ = on; }
8510+
84908511
inline void ClientImpl::set_socket_options(SocketOptions socket_options) {
84918512
socket_options_ = std::move(socket_options);
84928513
}

test/test.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -4652,7 +4652,7 @@ static bool send_request(time_t read_timeout_sec, const std::string &req,
46524652
auto error = Error::Success;
46534653

46544654
auto client_sock = detail::create_client_socket(
4655-
HOST, "", PORT, AF_UNSPEC, false, nullptr,
4655+
HOST, "", PORT, AF_UNSPEC, false, false, nullptr,
46564656
/*connection_timeout_sec=*/5, 0,
46574657
/*read_timeout_sec=*/5, 0,
46584658
/*write_timeout_sec=*/5, 0, std::string(), error);

0 commit comments

Comments
 (0)