return handle_EINTR([&]() {
return recv(sock,
#ifdef _WIN32
- static_cast<char *>(ptr),
- static_cast<int>(size),
+ static_cast<char *>(ptr), static_cast<int>(size),
#else
- ptr,
- size,
+ ptr, size,
#endif
flags);
});
}
-ssize_t send_socket(socket_t sock, const void *ptr, size_t size, int flags) {
+ssize_t send_socket(socket_t sock, const void *ptr, size_t size,
+ int flags) {
return handle_EINTR([&]() {
return send(sock,
#ifdef _WIN32
- static_cast<const char *>(ptr),
- static_cast<int>(size),
+ static_cast<const char *>(ptr), static_cast<int>(size),
#else
- ptr,
- size,
+ ptr, size,
#endif
flags);
});
#endif
}
+bool is_socket_alive(socket_t sock) {
+ const auto val = detail::select_read(sock, 0, 0);
+ if (val == 0) {
+ return true;
+ } else if (val < 0 && errno == EBADF) {
+ return false;
+ }
+ char buf[1];
+ return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0;
+}
+
class SocketStream : public Stream {
public:
SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
template <typename T>
bool
-process_server_socket_core(socket_t sock, size_t keep_alive_max_count,
+process_server_socket_core(const std::atomic<socket_t> &svr_sock, socket_t sock,
+ size_t keep_alive_max_count,
time_t keep_alive_timeout_sec, T callback) {
assert(keep_alive_max_count > 0);
auto ret = false;
auto count = keep_alive_max_count;
- while (count > 0 && keep_alive(sock, keep_alive_timeout_sec)) {
+ while (svr_sock != INVALID_SOCKET && count > 0 &&
+ keep_alive(sock, keep_alive_timeout_sec)) {
auto close_connection = count == 1;
auto connection_closed = false;
ret = callback(close_connection, connection_closed);
template <typename T>
bool
-process_server_socket(socket_t sock, size_t keep_alive_max_count,
+process_server_socket(const std::atomic<socket_t> &svr_sock, socket_t sock,
+ size_t keep_alive_max_count,
time_t keep_alive_timeout_sec, time_t read_timeout_sec,
time_t read_timeout_usec, time_t write_timeout_sec,
time_t write_timeout_usec, T callback) {
return process_server_socket_core(
- sock, keep_alive_max_count, keep_alive_timeout_sec,
+ svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
[&](bool close_connection, bool &connection_closed) {
SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
write_timeout_sec, write_timeout_usec);
}
template <typename BindOrConnect>
-socket_t create_socket(const char *host, int port, int address_family,
- int socket_flags, bool tcp_nodelay,
+socket_t create_socket(const char *host, const char *ip, int port,
+ int address_family, int socket_flags, bool tcp_nodelay,
SocketOptions socket_options,
BindOrConnect bind_or_connect) {
// Get address info
hints.ai_flags = socket_flags;
hints.ai_protocol = 0;
+ // Ask getaddrinfo to convert IP in c-string to address
+ if (ip[0] != '\0') {
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ }
+
auto service = std::to_string(port);
- if (getaddrinfo(host, service.c_str(), &hints, &result)) {
+ if (ip[0] != '\0' ? getaddrinfo(ip, service.c_str(), &hints, &result)
+ : getaddrinfo(host, service.c_str(), &hints, &result)) {
#if defined __linux__ && !defined __ANDROID__
res_init();
#endif
#endif
socket_t create_client_socket(
- const char *host, int port, int address_family, bool tcp_nodelay,
- SocketOptions socket_options, time_t connection_timeout_sec,
- time_t connection_timeout_usec, time_t read_timeout_sec,
- time_t read_timeout_usec, time_t write_timeout_sec,
+ const char *host, const char *ip, int port, int address_family,
+ bool tcp_nodelay, SocketOptions socket_options,
+ time_t connection_timeout_sec, time_t connection_timeout_usec,
+ time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
time_t write_timeout_usec, const std::string &intf, Error &error) {
auto sock = create_socket(
- host, port, address_family, 0, tcp_nodelay, std::move(socket_options),
+ host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options),
[&](socket_t sock2, struct addrinfo &ai) -> bool {
if (!intf.empty()) {
#ifdef USE_IF2IP
}
bool can_compress_content_type(const std::string &content_type) {
- return (!content_type.find("text/") && content_type != "text/event-stream") ||
+ return (!content_type.rfind("text/", 0) &&
+ content_type != "text/event-stream") ||
content_type == "image/svg+xml" ||
content_type == "application/javascript" ||
content_type == "application/json" ||
content_type == "application/xml" ||
+ content_type == "application/protobuf" ||
content_type == "application/xhtml+xml";
}
ret = inflate(&strm_, Z_NO_FLUSH);
- if (prev_avail_in - strm_.avail_in == 0) {
- return false;
- }
+ if (prev_avail_in - strm_.avail_in == 0) { return false; }
assert(ret != Z_STREAM_ERROR);
switch (ret) {
continue; // Skip invalid line.
}
+ if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
+
// Exclude CRLF
auto end = line_reader.ptr() + line_reader.size() - 2;
return !boundary.empty();
}
+#ifdef CPPHTTPLIB_NO_EXCEPTIONS
+bool parse_range_header(const std::string &s, Ranges &ranges) {
+#else
bool parse_range_header(const std::string &s, Ranges &ranges) try {
+#endif
static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))");
std::smatch m;
if (std::regex_match(s, m, re_first_range)) {
return all_valid_ranges;
}
return false;
+#ifdef CPPHTTPLIB_NO_EXCEPTIONS
+}
+#else
} catch (...) { return false; }
+#endif
class MultipartFormDataParser {
public:
static const std::string dash_ = "--";
static const std::string crlf_ = "\r\n";
- buf_.append(buf, n); // TODO: performance improvement
+ buf_append(buf, n);
- while (!buf_.empty()) {
+ while (buf_size() > 0) {
switch (state_) {
case 0: { // Initial boundary
auto pattern = dash_ + boundary_ + crlf_;
- if (pattern.size() > buf_.size()) { return true; }
- auto pos = buf_.find(pattern);
- if (pos != 0) { return false; }
- buf_.erase(0, pattern.size());
- off_ += pattern.size();
+ if (pattern.size() > buf_size()) { return true; }
+ if (!buf_start_with(pattern)) { return false; }
+ buf_erase(pattern.size());
state_ = 1;
break;
}
break;
}
case 2: { // Headers
- auto pos = buf_.find(crlf_);
- while (pos != std::string::npos) {
+ auto pos = buf_find(crlf_);
+ if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; }
+ while (pos < buf_size()) {
// Empty line
if (pos == 0) {
if (!header_callback(file_)) {
is_valid_ = false;
return false;
}
- buf_.erase(0, crlf_.size());
- off_ += crlf_.size();
+ buf_erase(crlf_.size());
state_ = 3;
break;
}
static const std::string header_name = "content-type:";
- const auto header = buf_.substr(0, pos);
+ const auto header = buf_head(pos);
if (start_with_case_ignore(header, header_name)) {
file_.content_type = trim_copy(header.substr(header_name.size()));
} else {
}
}
- buf_.erase(0, pos + crlf_.size());
- off_ += pos + crlf_.size();
- pos = buf_.find(crlf_);
+ buf_erase(pos + crlf_.size());
+ pos = buf_find(crlf_);
}
if (state_ != 3) { return true; }
break;
case 3: { // Body
{
auto pattern = crlf_ + dash_;
- if (pattern.size() > buf_.size()) { return true; }
+ if (pattern.size() > buf_size()) { return true; }
- auto pos = find_string(buf_, pattern);
+ auto pos = buf_find(pattern);
- if (!content_callback(buf_.data(), pos)) {
+ if (!content_callback(buf_data(), pos)) {
is_valid_ = false;
return false;
}
- off_ += pos;
- buf_.erase(0, pos);
+ buf_erase(pos);
}
{
auto pattern = crlf_ + dash_ + boundary_;
- if (pattern.size() > buf_.size()) { return true; }
+ if (pattern.size() > buf_size()) { return true; }
- auto pos = buf_.find(pattern);
- if (pos != std::string::npos) {
- if (!content_callback(buf_.data(), pos)) {
+ auto pos = buf_find(pattern);
+ if (pos < buf_size()) {
+ if (!content_callback(buf_data(), pos)) {
is_valid_ = false;
return false;
}
- off_ += pos + pattern.size();
- buf_.erase(0, pos + pattern.size());
+ buf_erase(pos + pattern.size());
state_ = 4;
} else {
- if (!content_callback(buf_.data(), pattern.size())) {
+ if (!content_callback(buf_data(), pattern.size())) {
is_valid_ = false;
return false;
}
- off_ += pattern.size();
- buf_.erase(0, pattern.size());
+ buf_erase(pattern.size());
}
}
break;
}
case 4: { // Boundary
- if (crlf_.size() > buf_.size()) { return true; }
- if (buf_.compare(0, crlf_.size(), crlf_) == 0) {
- buf_.erase(0, crlf_.size());
- off_ += crlf_.size();
+ if (crlf_.size() > buf_size()) { return true; }
+ if (buf_start_with(crlf_)) {
+ buf_erase(crlf_.size());
state_ = 1;
} else {
auto pattern = dash_ + crlf_;
- if (pattern.size() > buf_.size()) { return true; }
- if (buf_.compare(0, pattern.size(), pattern) == 0) {
- buf_.erase(0, pattern.size());
- off_ += pattern.size();
+ if (pattern.size() > buf_size()) { return true; }
+ if (buf_start_with(pattern)) {
+ buf_erase(pattern.size());
is_valid_ = true;
state_ = 5;
} else {
return true;
}
- bool start_with(const std::string &a, size_t off,
+ std::string boundary_;
+
+ size_t state_ = 0;
+ bool is_valid_ = false;
+ MultipartFormData file_;
+
+ // Buffer
+ bool start_with(const std::string &a, size_t spos, size_t epos,
const std::string &b) const {
- if (a.size() - off < b.size()) { return false; }
+ if (epos - spos < b.size()) { return false; }
for (size_t i = 0; i < b.size(); i++) {
- if (a[i + off] != b[i]) { return false; }
+ if (a[i + spos] != b[i]) { return false; }
}
return true;
}
- size_t find_string(const std::string &s, const std::string &pattern) const {
- auto c = pattern.front();
+ size_t buf_size() const { return buf_epos_ - buf_spos_; }
+
+ const char *buf_data() const { return &buf_[buf_spos_]; }
+
+ std::string buf_head(size_t l) const { return buf_.substr(buf_spos_, l); }
+
+ bool buf_start_with(const std::string &s) const {
+ return start_with(buf_, buf_spos_, buf_epos_, s);
+ }
+
+ size_t buf_find(const std::string &s) const {
+ auto c = s.front();
- size_t off = 0;
- while (off < s.size()) {
- auto pos = s.find(c, off);
- if (pos == std::string::npos) { return s.size(); }
+ size_t off = buf_spos_;
+ while (off < buf_epos_) {
+ auto pos = off;
+ while (true) {
+ if (pos == buf_epos_) { return buf_size(); }
+ if (buf_[pos] == c) { break; }
+ pos++;
+ }
- auto rem = s.size() - pos;
- if (pattern.size() > rem) { return pos; }
+ auto remaining_size = buf_epos_ - pos;
+ if (s.size() > remaining_size) { return buf_size(); }
- if (start_with(s, pos, pattern)) { return pos; }
+ if (start_with(buf_, pos, buf_epos_, s)) { return pos - buf_spos_; }
off = pos + 1;
}
- return s.size();
+ return buf_size();
}
- std::string boundary_;
+ void buf_append(const char *data, size_t n) {
+ auto remaining_size = buf_size();
+ if (remaining_size > 0 && buf_spos_ > 0) {
+ for (size_t i = 0; i < remaining_size; i++) {
+ buf_[i] = buf_[buf_spos_ + i];
+ }
+ }
+ buf_spos_ = 0;
+ buf_epos_ = remaining_size;
+
+ if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); }
+
+ for (size_t i = 0; i < n; i++) {
+ buf_[buf_epos_ + i] = data[i];
+ }
+ buf_epos_ += n;
+ }
+
+ void buf_erase(size_t size) { buf_spos_ += size; }
std::string buf_;
- size_t state_ = 0;
- bool is_valid_ = false;
- size_t off_ = 0;
- MultipartFormData file_;
+ size_t buf_spos_ = 0;
+ size_t buf_epos_ = 0;
};
std::string to_lower(const char *beg, const char *end) {
bool Request::is_multipart_form_data() const {
const auto &content_type = get_header_value("Content-Type");
- return !content_type.find("multipart/form-data");
+ return !content_type.rfind("multipart/form-data", 0);
}
bool Request::has_file(const char *key) const {
: sock_(sock), read_timeout_sec_(read_timeout_sec),
read_timeout_usec_(read_timeout_usec),
write_timeout_sec_(write_timeout_sec),
- write_timeout_usec_(write_timeout_usec),
- read_buff_(read_buff_size_, 0) {}
+ write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {}
SocketStream::~SocketStream() {}
ssize_t SocketStream::read(char *ptr, size_t size) {
#ifdef _WIN32
- size = (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
+ size =
+ (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
#else
- size = (std::min)(size, static_cast<size_t>((std::numeric_limits<ssize_t>::max)()));
+ size = (std::min)(size,
+ static_cast<size_t>((std::numeric_limits<ssize_t>::max)()));
#endif
if (read_buff_off_ < read_buff_content_size_) {
read_buff_content_size_ = 0;
if (size < read_buff_size_) {
- auto n = read_socket(sock_, read_buff_.data(), read_buff_size_, CPPHTTPLIB_RECV_FLAGS);
+ auto n = read_socket(sock_, read_buff_.data(), read_buff_size_,
+ CPPHTTPLIB_RECV_FLAGS);
if (n <= 0) {
return n;
} else if (n <= static_cast<ssize_t>(size)) {
if (!is_writable()) { return -1; }
#ifdef _WIN32
- size = (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
+ size =
+ (std::min)(size, static_cast<size_t>((std::numeric_limits<int>::max)()));
#endif
return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS);
Server::create_server_socket(const char *host, int port, int socket_flags,
SocketOptions socket_options) const {
return detail::create_socket(
- host, port, address_family_, socket_flags, tcp_nodelay_,
+ host, "", port, address_family_, socket_flags, tcp_nodelay_,
std::move(socket_options),
[](socket_t sock, struct addrinfo &ai) -> bool {
if (::bind(sock, ai.ai_addr, static_cast<socklen_t>(ai.ai_addrlen))) {
return false;
}
- if (::listen(sock, 5)) { // Listen through 5 channels
- return false;
- }
+ if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) { return false; }
return true;
});
}
// Rounting
bool routed = false;
+#ifdef CPPHTTPLIB_NO_EXCEPTIONS
+ routed = routing(req, res, strm);
+#else
try {
routed = routing(req, res, strm);
} catch (std::exception &e) {
res.status = 500;
res.set_header("EXCEPTION_WHAT", "UNKNOWN");
}
+#endif
if (routed) {
if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; }
bool Server::process_and_close_socket(socket_t sock) {
auto ret = detail::process_server_socket(
- sock, keep_alive_max_count_, keep_alive_timeout_sec_, read_timeout_sec_,
- read_timeout_usec_, write_timeout_sec_, write_timeout_usec_,
+ svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
+ read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
+ write_timeout_usec_,
[this](Stream &strm, bool close_connection, bool &connection_closed) {
return process_request(strm, close_connection, connection_closed,
nullptr);
socket_t ClientImpl::create_client_socket(Error &error) const {
if (!proxy_host_.empty() && proxy_port_ != -1) {
return detail::create_client_socket(
- proxy_host_.c_str(), proxy_port_, address_family_, tcp_nodelay_,
+ proxy_host_.c_str(), "", proxy_port_, address_family_, tcp_nodelay_,
socket_options_, connection_timeout_sec_, connection_timeout_usec_,
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
write_timeout_usec_, interface_, error);
}
+ // Check is custom IP specified for host_
+ std::string ip;
+ auto it = addr_map_.find(host_);
+ if (it != addr_map_.end()) ip = it->second;
+
return detail::create_client_socket(
- host_.c_str(), port_, address_family_, tcp_nodelay_, socket_options_,
- connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_,
- read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_,
- error);
+ host_.c_str(), ip.c_str(), port_, address_family_, tcp_nodelay_,
+ socket_options_, connection_timeout_sec_, connection_timeout_usec_,
+ read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
+ write_timeout_usec_, interface_, error);
}
bool ClientImpl::create_and_connect_socket(Socket &socket,
bool ClientImpl::read_response_line(Stream &strm, const Request &req,
Response &res) {
- std::array<char, 2048> buf;
+ std::array<char, 2048> buf{};
detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
{
std::lock_guard<std::mutex> guard(socket_mutex_);
+
// Set this to false immediately - if it ever gets set to true by the end of
// the request, we know another thread instructed us to close the socket.
socket_should_be_closed_when_request_is_done_ = false;
auto is_alive = false;
if (socket_.is_open()) {
- is_alive = detail::select_write(socket_.sock, 0, 0) > 0;
+ is_alive = detail::is_socket_alive(socket_.sock);
if (!is_alive) {
// Attempt to avoid sigpipe by shutting down nongracefully if it seems
// like the other side has already closed the connection Also, there
if (!req.has_header("Accept")) { req.headers.emplace("Accept", "*/*"); }
if (!req.has_header("User-Agent")) {
- req.headers.emplace("User-Agent", "cpp-httplib/0.9");
+ req.headers.emplace("User-Agent", "cpp-httplib/0.10.1");
}
if (req.body.empty()) {
void ClientImpl::set_url_encode(bool on) { url_encode_ = on; }
+void ClientImpl::set_hostname_addr_map(
+ const std::map<std::string, std::string> addr_map) {
+ addr_map_ = std::move(addr_map);
+}
+
void ClientImpl::set_default_headers(Headers headers) {
default_headers_ = std::move(headers);
}
}
template <typename T>
-bool
-process_server_socket_ssl(SSL *ssl, socket_t sock, size_t keep_alive_max_count,
- time_t keep_alive_timeout_sec,
- time_t read_timeout_sec, time_t read_timeout_usec,
- time_t write_timeout_sec, time_t write_timeout_usec,
- T callback) {
+bool process_server_socket_ssl(
+ const std::atomic<socket_t> &svr_sock, SSL *ssl, socket_t sock,
+ size_t keep_alive_max_count, time_t keep_alive_timeout_sec,
+ time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
+ time_t write_timeout_usec, T callback) {
return process_server_socket_core(
- sock, keep_alive_max_count, keep_alive_timeout_sec,
+ svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
[&](bool close_connection, bool &connection_closed) {
SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
write_timeout_sec, write_timeout_usec);
auto err = SSL_get_error(ssl_, ret);
int n = 1000;
#ifdef _WIN32
- while (--n >= 0 &&
- (err == SSL_ERROR_WANT_READ ||
- err == SSL_ERROR_SYSCALL && WSAGetLastError() == WSAETIMEDOUT)) {
+ while (--n >= 0 && (err == SSL_ERROR_WANT_READ ||
+ (err == SSL_ERROR_SYSCALL &&
+ WSAGetLastError() == WSAETIMEDOUT))) {
#else
while (--n >= 0 && err == SSL_ERROR_WANT_READ) {
#endif
auto err = SSL_get_error(ssl_, ret);
int n = 1000;
#ifdef _WIN32
- while (--n >= 0 &&
- (err == SSL_ERROR_WANT_WRITE ||
- err == SSL_ERROR_SYSCALL && WSAGetLastError() == WSAETIMEDOUT)) {
+ while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE ||
+ (err == SSL_ERROR_SYSCALL &&
+ WSAGetLastError() == WSAETIMEDOUT))) {
#else
while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) {
#endif
SSLServer::SSLServer(const char *cert_path, const char *private_key_path,
const char *client_ca_cert_file_path,
const char *client_ca_cert_dir_path) {
- ctx_ = SSL_CTX_new(TLS_method());
+ ctx_ = SSL_CTX_new(TLS_server_method());
if (ctx_) {
SSL_CTX_set_options(ctx_,
- SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
- SSL_OP_NO_COMPRESSION |
+ SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
- // auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- // SSL_CTX_set_tmp_ecdh(ctx_, ecdh);
- // EC_KEY_free(ecdh);
+ SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION);
if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 ||
SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) !=
SSL_CTX_free(ctx_);
ctx_ = nullptr;
} else if (client_ca_cert_file_path || client_ca_cert_dir_path) {
- // if (client_ca_cert_file_path) {
- // auto list = SSL_load_client_CA_file(client_ca_cert_file_path);
- // SSL_CTX_set_client_CA_list(ctx_, list);
- // }
-
SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path,
client_ca_cert_dir_path);
SSL_CTX_set_verify(
- ctx_,
- SSL_VERIFY_PEER |
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE,
- nullptr);
+ ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
}
}
}
SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
X509_STORE *client_ca_cert_store) {
- ctx_ = SSL_CTX_new(SSLv23_server_method());
+ ctx_ = SSL_CTX_new(TLS_server_method());
if (ctx_) {
SSL_CTX_set_options(ctx_,
- SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
- SSL_OP_NO_COMPRESSION |
+ SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
+ SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION);
+
if (SSL_CTX_use_certificate(ctx_, cert) != 1 ||
SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) {
SSL_CTX_free(ctx_);
ctx_ = nullptr;
} else if (client_ca_cert_store) {
-
SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
SSL_CTX_set_verify(
- ctx_,
- SSL_VERIFY_PEER |
- SSL_VERIFY_FAIL_IF_NO_PEER_CERT, // SSL_VERIFY_CLIENT_ONCE,
- nullptr);
+ ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
}
}
}
bool SSLServer::is_valid() const { return ctx_; }
+SSL_CTX *SSLServer::ssl_context() const { return ctx_; }
+
bool SSLServer::process_and_close_socket(socket_t sock) {
auto ssl = detail::ssl_new(
sock, ctx_, ctx_mutex_,
bool ret = false;
if (ssl) {
ret = detail::process_server_socket_ssl(
- ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
+ svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
write_timeout_usec_,
[this, ssl](Stream &strm, bool close_connection,
const std::string &client_cert_path,
const std::string &client_key_path)
: ClientImpl(host, port, client_cert_path, client_key_path) {
- ctx_ = SSL_CTX_new(SSLv23_client_method());
+ ctx_ = SSL_CTX_new(TLS_client_method());
detail::split(&host_[0], &host_[host_.size()], '.',
[&](const char *b, const char *e) {
host_components_.emplace_back(std::string(b, e));
});
+
if (!client_cert_path.empty() && !client_key_path.empty()) {
if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(),
SSL_FILETYPE_PEM) != 1 ||
SSLClient::SSLClient(const std::string &host, int port,
X509 *client_cert, EVP_PKEY *client_key)
: ClientImpl(host, port) {
- ctx_ = SSL_CTX_new(SSLv23_client_method());
+ ctx_ = SSL_CTX_new(TLS_client_method());
detail::split(&host_[0], &host_[host_.size()], '.',
[&](const char *b, const char *e) {
host_components_.emplace_back(std::string(b, e));
});
+
if (client_cert != nullptr && client_key != nullptr) {
if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 ||
SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) {
#else
if (!scheme.empty() && scheme != "http") {
#endif
+#ifndef CPPHTTPLIB_NO_EXCEPTIONS
std::string msg = "'" + scheme + "' scheme is not supported.";
throw std::invalid_argument(msg);
+#endif
return;
}
void Client::stop() { cli_->stop(); }
+void Client::set_hostname_addr_map(
+ const std::map<std::string, std::string> addr_map) {
+ cli_->set_hostname_addr_map(std::move(addr_map));
+}
+
void Client::set_default_headers(Headers headers) {
cli_->set_default_headers(std::move(headers));
}