Skip to content

std::chrono::duration for timeout #890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
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
174 changes: 103 additions & 71 deletions httplib.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,26 @@ using Logger = std::function<void(const Request &, const Response &)>;

using SocketOptions = std::function<void(socket_t sock)>;

class Timeout {
public:
Timeout(time_t sec, time_t usec) : _sec(sec), _usec(usec) {}

template <class Rep, class Period>
Timeout(const std::chrono::duration<Rep, Period> &time) {
_sec = std::chrono::duration_cast<std::chrono::seconds>(time).count();
_usec = std::chrono::duration_cast<std::chrono::microseconds>(
time - std::chrono::seconds(_sec))
.count();
}

time_t sec() const { return _sec; }
time_t usec() const { return _usec; }

private:
time_t _sec;
time_t _usec;
};

inline void default_socket_options(socket_t sock) {
int yes = 1;
#ifdef _WIN32
Expand Down Expand Up @@ -668,9 +688,13 @@ class Server {

Server &set_keep_alive_max_count(size_t count);
Server &set_keep_alive_timeout(time_t sec);
Server &set_read_timeout(time_t sec, time_t usec = 0);
Server &set_write_timeout(time_t sec, time_t usec = 0);
Server &set_idle_interval(time_t sec, time_t usec = 0);

template <class Rep, class Period>
Server &set_read_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
Server &set_write_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
Server &set_idle_interval(const std::chrono::duration<Rep, Period> &time);

Server &set_payload_max_length(size_t length);

Expand All @@ -692,14 +716,15 @@ class Server {

std::atomic<socket_t> svr_sock_;
size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;

Timeout read_timeout_ = {CPPHTTPLIB_READ_TIMEOUT_SECOND,
CPPHTTPLIB_READ_TIMEOUT_USECOND};
Timeout write_timeout_ = {CPPHTTPLIB_WRITE_TIMEOUT_SECOND,
CPPHTTPLIB_WRITE_TIMEOUT_USECOND};
Timeout idle_interval_ = {CPPHTTPLIB_IDLE_INTERVAL_SECOND,
CPPHTTPLIB_IDLE_INTERVAL_USECOND};

private:
using Handlers = std::vector<std::pair<std::regex, Handler>>;
Expand Down Expand Up @@ -965,9 +990,12 @@ class ClientImpl {
void set_tcp_nodelay(bool on);
void set_socket_options(SocketOptions socket_options);

void set_connection_timeout(time_t sec, time_t usec = 0);
void set_read_timeout(time_t sec, time_t usec = 0);
void set_write_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_connection_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
void set_read_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
void set_write_timeout(const std::chrono::duration<Rep, Period> &time);

void set_basic_auth(const char *username, const char *password);
void set_bearer_token_auth(const char *token);
Expand Down Expand Up @@ -1056,12 +1084,12 @@ class ClientImpl {
std::string client_cert_path_;
std::string client_key_path_;

time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
Timeout connection_timeout_ = {CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND,
CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND};
Timeout read_timeout_ = {CPPHTTPLIB_READ_TIMEOUT_SECOND,
CPPHTTPLIB_READ_TIMEOUT_USECOND};
Timeout write_timeout_ = {CPPHTTPLIB_WRITE_TIMEOUT_SECOND,
CPPHTTPLIB_WRITE_TIMEOUT_USECOND};

std::string basic_auth_username_;
std::string basic_auth_password_;
Expand Down Expand Up @@ -1267,9 +1295,12 @@ class Client {
void set_tcp_nodelay(bool on);
void set_socket_options(SocketOptions socket_options);

void set_connection_timeout(time_t sec, time_t usec = 0);
void set_read_timeout(time_t sec, time_t usec = 0);
void set_write_timeout(time_t sec, time_t usec = 0);
template <class Rep, class Period>
void set_connection_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
void set_read_timeout(const std::chrono::duration<Rep, Period> &time);
template <class Rep, class Period>
void set_write_timeout(const std::chrono::duration<Rep, Period> &time);

void set_basic_auth(const char *username, const char *password);
void set_bearer_token_auth(const char *token);
Expand Down Expand Up @@ -4374,23 +4405,23 @@ inline Server &Server::set_keep_alive_timeout(time_t sec) {
return *this;
}

inline Server &Server::set_read_timeout(time_t sec, time_t usec) {
read_timeout_sec_ = sec;
read_timeout_usec_ = usec;
template <class Rep, class Period>
inline Server &Server::set_read_timeout(const std::chrono::duration<Rep, Period> &time) {
read_timeout_ = time;

return *this;
}

inline Server &Server::set_write_timeout(time_t sec, time_t usec) {
write_timeout_sec_ = sec;
write_timeout_usec_ = usec;
template <class Rep, class Period>
inline Server &Server::set_write_timeout(const std::chrono::duration<Rep, Period> &time) {
write_timeout_ = time;

return *this;
}

inline Server &Server::set_idle_interval(time_t sec, time_t usec) {
idle_interval_sec_ = sec;
idle_interval_usec_ = usec;
template <class Rep, class Period>
inline Server &Server::set_idle_interval(const std::chrono::duration<Rep, Period> &time) {
idle_interval_ = time;

return *this;
}
Expand Down Expand Up @@ -4759,10 +4790,10 @@ inline bool Server::listen_internal() {

while (svr_sock_ != INVALID_SOCKET) {
#ifndef _WIN32
if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) {
if (idle_interval_.sec() > 0 || idle_interval_.usec() > 0) {
#endif
auto val = detail::select_read(svr_sock_, idle_interval_sec_,
idle_interval_usec_);
auto val = detail::select_read(svr_sock_, idle_interval_.sec(),
idle_interval_.usec());
if (val == 0) { // Timeout
task_queue->on_idle();
continue;
Expand Down Expand Up @@ -5131,8 +5162,8 @@ inline bool Server::is_valid() const { return true; }

inline 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_,
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);
Expand Down Expand Up @@ -5165,11 +5196,9 @@ inline bool ClientImpl::is_valid() const { return true; }
inline void ClientImpl::copy_settings(const ClientImpl &rhs) {
client_cert_path_ = rhs.client_cert_path_;
client_key_path_ = rhs.client_key_path_;
connection_timeout_sec_ = rhs.connection_timeout_sec_;
read_timeout_sec_ = rhs.read_timeout_sec_;
read_timeout_usec_ = rhs.read_timeout_usec_;
write_timeout_sec_ = rhs.write_timeout_sec_;
write_timeout_usec_ = rhs.write_timeout_usec_;
connection_timeout_ = rhs.connection_timeout_;
read_timeout_ = rhs.read_timeout_;
write_timeout_ = rhs.write_timeout_;
basic_auth_username_ = rhs.basic_auth_username_;
basic_auth_password_ = rhs.basic_auth_password_;
bearer_token_auth_token_ = rhs.bearer_token_auth_token_;
Expand Down Expand Up @@ -5203,11 +5232,11 @@ inline 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_, tcp_nodelay_, socket_options_,
connection_timeout_sec_, connection_timeout_usec_, interface_, error);
connection_timeout_.sec(), connection_timeout_.usec(), interface_, error);
}
return detail::create_client_socket(
host_.c_str(), port_, tcp_nodelay_, socket_options_,
connection_timeout_sec_, connection_timeout_usec_, interface_, error);
connection_timeout_.sec(), connection_timeout_.usec(), interface_, error);
}

inline bool ClientImpl::create_and_connect_socket(Socket &socket,
Expand Down Expand Up @@ -5814,8 +5843,8 @@ inline bool
ClientImpl::process_socket(const Socket &socket,
std::function<bool(Stream &strm)> callback) {
return detail::process_client_socket(
socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
write_timeout_usec_, std::move(callback));
socket.sock, read_timeout_.sec(), read_timeout_.usec(), write_timeout_.sec(),
write_timeout_.usec(), std::move(callback));
}

inline bool ClientImpl::is_ssl() const { return false; }
Expand Down Expand Up @@ -6268,19 +6297,19 @@ inline void ClientImpl::stop() {
close_socket(socket_);
}

inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) {
connection_timeout_sec_ = sec;
connection_timeout_usec_ = usec;
template <class Rep, class Period>
inline void ClientImpl::set_connection_timeout(const std::chrono::duration<Rep, Period> &time) {
connection_timeout_ = time;
}

inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) {
read_timeout_sec_ = sec;
read_timeout_usec_ = usec;
template <class Rep, class Period>
inline void ClientImpl::set_read_timeout(const std::chrono::duration<Rep, Period> &time) {
read_timeout_ = time;
}

inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) {
write_timeout_sec_ = sec;
write_timeout_usec_ = usec;
template <class Rep, class Period>
inline void ClientImpl::set_write_timeout(const std::chrono::duration<Rep, Period> &time) {
write_timeout_ = time;
}

inline void ClientImpl::set_basic_auth(const char *username,
Expand Down Expand Up @@ -6643,16 +6672,16 @@ inline bool SSLServer::process_and_close_socket(socket_t sock) {
sock, ctx_, ctx_mutex_,
[&](SSL *ssl) {
return detail::ssl_connect_or_accept_nonblocking(
sock, ssl, SSL_accept, read_timeout_sec_, read_timeout_usec_);
sock, ssl, SSL_accept, read_timeout_.sec(), read_timeout_.usec());
},
[](SSL * /*ssl*/) { return true; });

bool ret = false;
if (ssl) {
ret = detail::process_server_socket_ssl(
ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
write_timeout_usec_,
read_timeout_.sec(), read_timeout_.usec(), write_timeout_.sec(),
write_timeout_.usec(),
[this, ssl](Stream &strm, bool close_connection,
bool &connection_closed) {
return process_request(strm, close_connection, connection_closed,
Expand Down Expand Up @@ -6761,8 +6790,8 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
success = true;
Response res2;
if (!detail::process_client_socket(
socket.sock, read_timeout_sec_, read_timeout_usec_,
write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
socket.sock, read_timeout_.sec(), read_timeout_.usec(),
write_timeout_.sec(), write_timeout_.usec(), [&](Stream &strm) {
Request req2;
req2.method = "CONNECT";
req2.path = host_and_port_;
Expand All @@ -6784,8 +6813,8 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
if (detail::parse_www_authenticate(res2, auth, true)) {
Response res3;
if (!detail::process_client_socket(
socket.sock, read_timeout_sec_, read_timeout_usec_,
write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
socket.sock, read_timeout_.sec(), read_timeout_.usec(),
write_timeout_.sec(), write_timeout_.usec(), [&](Stream &strm) {
Request req3;
req3.method = "CONNECT";
req3.path = host_and_port_;
Expand Down Expand Up @@ -6853,8 +6882,8 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
}

if (!detail::ssl_connect_or_accept_nonblocking(
socket.sock, ssl, SSL_connect, connection_timeout_sec_,
connection_timeout_usec_)) {
socket.sock, ssl, SSL_connect, connection_timeout_.sec(),
connection_timeout_.usec())) {
error = Error::SSLConnection;
return false;
}
Expand Down Expand Up @@ -6916,8 +6945,8 @@ SSLClient::process_socket(const Socket &socket,
std::function<bool(Stream &strm)> callback) {
assert(socket.ssl);
return detail::process_client_socket_ssl(
socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_,
write_timeout_sec_, write_timeout_usec_, std::move(callback));
socket.ssl, socket.sock, read_timeout_.sec(), read_timeout_.usec(),
write_timeout_.sec(), write_timeout_.usec(), std::move(callback));
}

inline bool SSLClient::is_ssl() const { return true; }
Expand Down Expand Up @@ -7376,14 +7405,17 @@ inline void Client::set_socket_options(SocketOptions socket_options) {
cli_->set_socket_options(std::move(socket_options));
}

inline void Client::set_connection_timeout(time_t sec, time_t usec) {
cli_->set_connection_timeout(sec, usec);
template <class Rep, class Period>
inline void Client::set_connection_timeout(const std::chrono::duration<Rep, Period> &time) {
cli_->set_connection_timeout(time);
}
inline void Client::set_read_timeout(time_t sec, time_t usec) {
cli_->set_read_timeout(sec, usec);
template <class Rep, class Period>
inline void Client::set_read_timeout(const std::chrono::duration<Rep, Period> &time) {
cli_->set_read_timeout(time);
}
inline void Client::set_write_timeout(time_t sec, time_t usec) {
cli_->set_write_timeout(sec, usec);
template <class Rep, class Period>
inline void Client::set_write_timeout(const std::chrono::duration<Rep, Period> &time) {
cli_->set_write_timeout(time);
}

inline void Client::set_basic_auth(const char *username, const char *password) {
Expand Down
Loading