values can be handled correctly.
Also make sure sdig uses a NB socket, to handle timeouts correctly.
s.setNonBlocking();
s.connect(remote, 2);
- writen2WithTimeout(s.getHandle(), msg.c_str(), msg.length(), 2);
+ writen2WithTimeout(s.getHandle(), msg.c_str(), msg.length(), timeval{2,0});
} catch (runtime_error &e){
g_log<<Logger::Warning<<"Unable to write data to carbon server at "<<remote.toStringWithPort()<<": "<<e.what()<<endl;
continue;
auto tmp = ci.release();
try {
// throws on failure
- writen2WithTimeout(pipe, &tmp, sizeof(tmp), 0);
+ writen2WithTimeout(pipe, &tmp, sizeof(tmp), timeval{0,0});
}
catch (...) {
delete tmp;
socket->setNonBlocking();
gettimeofday(&d_connectionStartTime, nullptr);
- auto handler = std::make_unique<TCPIOHandler>("", socket->releaseHandle(), 0, d_ds->d_tlsCtx, time(nullptr));
+ auto handler = std::make_unique<TCPIOHandler>("", socket->releaseHandle(), timeval{0,0}, d_ds->d_tlsCtx, time(nullptr));
handler->tryConnect(d_ds->tcpFastOpen && isFastOpenEnabled(), d_ds->remote);
d_queries = 0;
class IncomingTCPConnectionState
{
public:
- IncomingTCPConnectionState(ConnectionInfo&& ci, TCPClientThreadData& threadData, const struct timeval& now): d_buffer(s_maxPacketCacheEntrySize), d_threadData(threadData), d_ci(std::move(ci)), d_handler(d_ci.fd, g_tcpRecvTimeout, d_ci.cs->tlsFrontend ? d_ci.cs->tlsFrontend->getContext() : nullptr, now.tv_sec), d_ioState(make_unique<IOStateHandler>(threadData.mplexer, d_ci.fd)), d_connectionStartTime(now)
+ IncomingTCPConnectionState(ConnectionInfo&& ci, TCPClientThreadData& threadData, const struct timeval& now): d_buffer(s_maxPacketCacheEntrySize), d_threadData(threadData), d_ci(std::move(ci)), d_handler(d_ci.fd, timeval{g_tcpRecvTimeout,0}, d_ci.cs->tlsFrontend ? d_ci.cs->tlsFrontend->getContext() : nullptr, now.tv_sec), d_ioState(make_unique<IOStateHandler>(threadData.mplexer, d_ci.fd)), d_connectionStartTime(now)
{
d_origDest.reset();
d_origDest.sin4.sin_family = d_ci.remote.sin4.sin_family;
{
}
- void connect(bool fastOpen, const ComboAddress& remote, unsigned int timeout) override
+ void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout) override
{
}
- size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0) override
+ size_t read(void* buffer, size_t bufferSize, const struct timeval&readTimeout, const struct timeval& totalTimeout={0,0}) override
{
return 0;
}
- size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) override
+ size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout) override
{
return 0;
}
{
}
- std::unique_ptr<TLSConnection> getConnection(int socket, unsigned int timeout, time_t now) override
+ std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) override
{
return std::make_unique<MockupTLSConnection>(socket);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, unsigned int timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
{
return std::make_unique<MockupTLSConnection>(socket, true);
}
uint16_t len=htons(r->getString().length());
string buffer((const char*)&len, 2);
buffer.append(r->getString());
- writen2WithTimeout(r->getSocket(), buffer.c_str(), buffer.length(), ::arg().asNum("tcp-idle-timeout"));
+ writen2WithTimeout(r->getSocket(), buffer.c_str(), buffer.length(), timeval{::arg().asNum("tcp-idle-timeout"),0});
return true;
}
g_log << u << s << std::endl;
}
+inline void dolog(const char* s)
+{
+ g_log << s << std::endl;
+}
+
template<typename T, typename... Args>
void dolog(Logger::Urgency u, const char* s, T value, Args... args)
{
else {
g_log << value;
s += 2;
- dolog(u, s, args...);
+ dolog(s, args...);
return;
}
}
return ret;
}
-int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout)
+int SConnectWithTimeout(int sockfd, const ComboAddress& remote, const struct timeval& timeout)
{
int ret = connect(sockfd, reinterpret_cast<const struct sockaddr*>(&remote), remote.getSocklen());
if(ret < 0) {
int savederrno = errno;
if (savederrno == EINPROGRESS) {
- if (timeout <= 0) {
+ if (timeout <= timeval{0,0}) {
return savederrno;
}
/* we wait until the connection has been established */
bool error = false;
bool disconnected = false;
- int res = waitForRWData(sockfd, false, timeout, 0, &error, &disconnected);
+ int res = waitForRWData(sockfd, false, timeout.tv_sec, timeout.tv_usec, &error, &disconnected);
if (res == 1) {
if (error) {
savederrno = 0;
sockfd should be set to non-blocking beforehand.
returns 0 on success (the socket is writable), throw a
runtime_error otherwise */
-int SConnectWithTimeout(int sockfd, const ComboAddress& remote, int timeout);
+int SConnectWithTimeout(int sockfd, const ComboAddress& remote, const struct timeval& timeout);
int SBind(int sockfd, const ComboAddress& local);
int SAccept(int sockfd, ComboAddress& remote);
int SListen(int sockfd, int limit);
uint16_t toRead;
readn2(cfd, &toRead, sizeof(toRead));
toRead = std::min(ntohs(toRead), static_cast<uint16_t>(sizeof(buf)));
- res = readn2WithTimeout(cfd, &buf, toRead, 2);
+ res = readn2WithTimeout(cfd, &buf, toRead, timeval{2,0});
g_log<<Logger::Debug<<prefix<<"Had message of "<<std::to_string(toRead)<<" bytes from "<<saddr.toStringWithPort()<<endl;
} catch (runtime_error &e) {
g_log<<Logger::Warning<<prefix<<"Could not read message from "<<saddr.toStringWithPort()<<": "<<e.what()<<endl;
}
else {
try {
- const int timeout = (g_networkTimeoutMsec + 999) / 1000; // XXX tcpiohandler's unit is seconds
+ const struct timeval timeout{ g_networkTimeoutMsec / 1000, g_networkTimeoutMsec % 1000 * 1000};
Socket s(ip.sin4.sin_family, SOCK_STREAM);
s.setNonBlocking();
return len;
}
-size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout)
+size_t readn2WithTimeout(int fd, void* buffer, size_t len, const struct timeval& idleTimeout, const struct timeval& totalTimeout)
{
size_t pos = 0;
- time_t start = 0;
- int remainingTime = totalTimeout;
- if (totalTimeout) {
- start = time(nullptr);
+ struct timeval start{0,0};
+ struct timeval remainingTime = totalTimeout;
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ gettimeofday(&start, nullptr);
}
do {
}
else {
if (errno == EAGAIN) {
- int res = waitForData(fd, (totalTimeout == 0 || idleTimeout <= remainingTime) ? idleTimeout : remainingTime);
+ struct timeval w = ((totalTimeout.tv_sec == 0 && totalTimeout.tv_usec == 0) || idleTimeout <= remainingTime) ? idleTimeout : remainingTime;
+ int res = waitForData(fd, w.tv_sec, w.tv_usec);
if (res > 0) {
/* there is data available */
}
}
}
- if (totalTimeout) {
- time_t now = time(nullptr);
- int elapsed = now - start;
- if (elapsed >= remainingTime) {
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ struct timeval elapsed = now - start;
+ if (remainingTime < elapsed) {
throw runtime_error("Timeout while reading data");
}
start = now;
- remainingTime -= elapsed;
+ remainingTime = remainingTime - elapsed;
}
}
while (pos < len);
return len;
}
-size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout)
+size_t writen2WithTimeout(int fd, const void * buffer, size_t len, const struct timeval& timeout)
{
size_t pos = 0;
do {
throw runtime_error("EOF while writing message");
else {
if (errno == EAGAIN) {
- int res = waitForRWData(fd, false, timeout, 0);
+ int res = waitForRWData(fd, false, timeout.tv_sec, timeout.tv_usec);
if (res > 0) {
/* there is room available */
}
size_t writen2(int fd, const void *buf, size_t count);
inline size_t writen2(int fd, const std::string &s) { return writen2(fd, s.data(), s.size()); }
size_t readn2(int fd, void* buffer, size_t len);
-size_t readn2WithTimeout(int fd, void* buffer, size_t len, int idleTimeout, int totalTimeout=0);
-size_t writen2WithTimeout(int fd, const void * buffer, size_t len, int timeout);
+size_t readn2WithTimeout(int fd, void* buffer, size_t len, const struct timeval& idleTimeout, const struct timeval& totalTimeout={0,0});
+size_t writen2WithTimeout(int fd, const void * buffer, size_t len, const struct timeval& timeout);
void toLowerInPlace(string& str);
const string toLower(const string &upper);
inline bool operator<(const struct timeval& lhs, const struct timeval& rhs)
{
- return make_pair(lhs.tv_sec, lhs.tv_usec) < make_pair(rhs.tv_sec, rhs.tv_usec);
+ return tie(lhs.tv_sec, lhs.tv_usec) < tie(rhs.tv_sec, rhs.tv_usec);
+}
+inline bool operator<=(const struct timeval& lhs, const struct timeval& rhs)
+{
+ return tie(lhs.tv_sec, lhs.tv_usec) <= tie(rhs.tv_sec, rhs.tv_usec);
}
inline bool operator<(const struct timespec& lhs, const struct timespec& rhs)
Socket s(remote.sin4.sin_family, SOCK_STREAM);
s.setNonBlocking();
std::shared_ptr<TLSCtx> tlsCtx{nullptr};
- const int timeout = (g_networkTimeoutMsec + 999) / 1000; // XXX tcpiohandler's unit is seconds
+ const struct timeval timeout{g_networkTimeoutMsec / 1000, g_networkTimeoutMsec % 1000 * 1000};
auto handler = std::make_shared<TCPIOHandler>("", s.releaseHandle(), timeout, tlsCtx, time(nullptr));
handler->tryConnect(SyncRes::s_tcp_fast_open_connect, remote);// we do the connect so the first attempt happens while we gather stats
int main(int argc, char** argv)
try {
/* default timeout of 10s */
- int timeout = 10;
+ struct timeval timeout{10,0};
bool dnssec = false;
bool recurse = false;
bool tcp = false;
mch.insert(std::make_pair("Accept", "application/dns-message"));
string question(packet.begin(), packet.end());
// FIXME: how do we use proxyheader here?
- reply = mc.postURL(argv[1], question, mch, timeout, fastOpen);
+ reply = mc.postURL(argv[1], question, mch, timeout.tv_sec, fastOpen);
printReply(reply, showflags, hidesoadetails, dumpluaraw);
#else
throw PDNSException("please link sdig against libcurl for DoH support");
}
uint16_t counter = 0;
Socket sock(dest.sin4.sin_family, SOCK_STREAM);
+ sock.setNonBlocking();
setTCPNoDelay(sock.getHandle()); // disable NAGLE, which does not play nicely with delayed ACKs
TCPIOHandler handler(subjectName, sock.releaseHandle(), timeout, tlsCtx, time(nullptr));
handler.connect(fastOpen, dest, timeout);
Socket sock(dest.sin4.sin_family, SOCK_DGRAM);
question = proxyheader + question;
sock.sendTo(question, dest);
- int result = waitForData(sock.getHandle(), timeout);
+ int result = waitForData(sock.getHandle(), timeout.tv_sec, timeout.tv_usec);
if (result < 0)
throw std::runtime_error("Error waiting for data: " + stringerror());
if (!result)
//! Connect the socket to a specified endpoint
void connect(const ComboAddress &ep, int timeout=0)
{
- SConnectWithTimeout(d_socket, ep, timeout);
+ SConnectWithTimeout(d_socket, ep, timeval{timeout,0});
}
{
public:
/* server side connection */
- OpenSSLTLSConnection(int socket, unsigned int timeout, std::shared_ptr<OpenSSLFrontendContext> feContext): d_feContext(feContext), d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(d_feContext->d_tlsCtx.get()), SSL_free)), d_timeout(timeout)
+ OpenSSLTLSConnection(int socket, const struct timeval& timeout, std::shared_ptr<OpenSSLFrontendContext> feContext): d_feContext(feContext), d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(d_feContext->d_tlsCtx.get()), SSL_free)), d_timeout(timeout)
{
d_socket = socket;
}
/* client-side connection */
- OpenSSLTLSConnection(const std::string& hostname, int socket, unsigned int timeout, SSL_CTX* tlsCtx): d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(tlsCtx), SSL_free)), d_hostname(hostname), d_timeout(timeout)
+ OpenSSLTLSConnection(const std::string& hostname, int socket, const struct timeval& timeout, SSL_CTX* tlsCtx): d_conn(std::unique_ptr<SSL, void(*)(SSL*)>(SSL_new(tlsCtx), SSL_free)), d_hostname(hostname), d_timeout(timeout)
{
d_socket = socket;
}
}
- void handleIORequest(int res, unsigned int timeout)
+ void handleIORequest(int res, const struct timeval& timeout)
{
auto state = convertIORequestToIOState(res);
if (state == IOState::NeedRead) {
- res = waitForData(d_socket, timeout);
+ res = waitForData(d_socket, timeout.tv_sec, timeout.tv_usec);
if (res == 0) {
throw std::runtime_error("Timeout while reading from TLS connection");
}
}
}
else if (state == IOState::NeedWrite) {
- res = waitForRWData(d_socket, false, timeout, 0);
+ res = waitForRWData(d_socket, false, timeout.tv_sec, timeout.tv_usec);
if (res == 0) {
throw std::runtime_error("Timeout while writing to TLS connection");
}
throw std::runtime_error("Error establishing a TLS connection");
}
- void connect(bool fastOpen, const ComboAddress& remote, unsigned int timeout) override
+ void connect(bool fastOpen, const ComboAddress& remote, const struct timeval &timeout) override
{
/* sorry */
(void) fastOpen;
(void) remote;
- time_t start = 0;
- unsigned int remainingTime = timeout;
- if (timeout) {
- start = time(nullptr);
+ struct timeval start{0,0};
+ struct timeval remainingTime = timeout;
+ if (timeout.tv_sec != 0 || timeout.tv_usec != 0) {
+ gettimeofday(&start, nullptr);
}
int res = 0;
handleIORequest(res, remainingTime);
}
- if (timeout) {
- time_t now = time(nullptr);
- unsigned int elapsed = now - start;
- if (now < start || elapsed >= remainingTime) {
+ if (timeout.tv_sec != 0 || timeout.tv_usec != 0) {
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ struct timeval elapsed = now - start;
+ if (now < start || remainingTime < elapsed) {
throw runtime_error("Timeout while establishing TLS connection");
}
start = now;
- remainingTime -= elapsed;
+ remainingTime = remainingTime - elapsed;
}
}
while (res != 1);
return IOState::Done;
}
- size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout) override
+ size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout) override
{
size_t got = 0;
- time_t start = 0;
- unsigned int remainingTime = totalTimeout;
- if (totalTimeout) {
- start = time(nullptr);
+ struct timeval start = {0, 0};
+ struct timeval remainingTime = totalTimeout;
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ gettimeofday(&start, nullptr);
}
do {
got += static_cast<size_t>(res);
}
- if (totalTimeout) {
- time_t now = time(nullptr);
- unsigned int elapsed = now - start;
- if (now < start || elapsed >= remainingTime) {
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ struct timeval elapsed = now - start;
+ if (now < start || remainingTime < elapsed) {
throw runtime_error("Timeout while reading data");
}
start = now;
- remainingTime -= elapsed;
+ remainingTime = remainingTime - elapsed;
}
}
while (got < bufferSize);
return got;
}
- size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) override
+ size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout) override
{
size_t got = 0;
do {
std::shared_ptr<OpenSSLFrontendContext> d_feContext;
std::unique_ptr<SSL, void(*)(SSL*)> d_conn;
std::string d_hostname;
- unsigned int d_timeout;
+ struct timeval d_timeout;
};
std::atomic_flag OpenSSLTLSConnection::s_initTLSConnIndex = ATOMIC_FLAG_INIT;
return libssl_ocsp_stapling_callback(ssl, *ocspMap);
}
- std::unique_ptr<TLSConnection> getConnection(int socket, unsigned int timeout, time_t now) override
+ std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) override
{
handleTicketsKeyRotation(now);
return std::make_unique<OpenSSLTLSConnection>(socket, timeout, d_feContext);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, unsigned int timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
{
return std::make_unique<OpenSSLTLSConnection>(host, socket, timeout, d_tlsCtx.get());
}
{
public:
/* server side connection */
- GnuTLSConnection(int socket, unsigned int timeout, const gnutls_certificate_credentials_t creds, const gnutls_priority_t priorityCache, std::shared_ptr<GnuTLSTicketsKey>& ticketsKey, bool enableTickets): d_conn(std::unique_ptr<gnutls_session_int, void(*)(gnutls_session_t)>(nullptr, gnutls_deinit)), d_ticketsKey(ticketsKey)
+ GnuTLSConnection(int socket, const struct timeval& timeout, const gnutls_certificate_credentials_t creds, const gnutls_priority_t priorityCache, std::shared_ptr<GnuTLSTicketsKey>& ticketsKey, bool enableTickets): d_conn(std::unique_ptr<gnutls_session_int, void(*)(gnutls_session_t)>(nullptr, gnutls_deinit)), d_ticketsKey(ticketsKey)
{
unsigned int sslOptions = GNUTLS_SERVER | GNUTLS_NONBLOCK;
#ifdef GNUTLS_NO_SIGNAL
gnutls_transport_set_int(d_conn.get(), d_socket);
/* timeouts are in milliseconds */
- gnutls_handshake_set_timeout(d_conn.get(), timeout * 1000);
- gnutls_record_set_timeout(d_conn.get(), timeout * 1000);
+ gnutls_handshake_set_timeout(d_conn.get(), timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+ gnutls_record_set_timeout(d_conn.get(), timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
}
/* client-side connection */
- GnuTLSConnection(const std::string& host, int socket, unsigned int timeout, const gnutls_certificate_credentials_t creds, const gnutls_priority_t priorityCache, bool validateCerts): d_conn(std::unique_ptr<gnutls_session_int, void(*)(gnutls_session_t)>(nullptr, gnutls_deinit)), d_host(host)
+ GnuTLSConnection(const std::string& host, int socket, const struct timeval& timeout, const gnutls_certificate_credentials_t creds, const gnutls_priority_t priorityCache, bool validateCerts): d_conn(std::unique_ptr<gnutls_session_int, void(*)(gnutls_session_t)>(nullptr, gnutls_deinit)), d_host(host)
{
unsigned int sslOptions = GNUTLS_CLIENT | GNUTLS_NONBLOCK;
#ifdef GNUTLS_NO_SIGNAL
gnutls_transport_set_int(d_conn.get(), d_socket);
/* timeouts are in milliseconds */
- gnutls_handshake_set_timeout(d_conn.get(), timeout * 1000);
- gnutls_record_set_timeout(d_conn.get(), timeout * 1000);
+ gnutls_handshake_set_timeout(d_conn.get(), timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
+ gnutls_record_set_timeout(d_conn.get(), timeout.tv_sec * 1000 + timeout.tv_usec / 1000);
#if HAVE_GNUTLS_SESSION_SET_VERIFY_CERT
if (validateCerts && !d_host.empty()) {
throw std::runtime_error("Error establishing a new connection: " + std::string(gnutls_strerror(ret)));
}
- void connect(bool fastOpen, const ComboAddress& remote, unsigned int timeout) override
+ void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout) override
{
- time_t start = 0;
- unsigned int remainingTime = timeout;
- if (timeout) {
- start = time(nullptr);
+ struct timeval start = {0, 0};
+ struct timeval remainingTime = timeout;
+ if (timeout.tv_sec != 0 || timeout.tv_usec != 0) {
+ gettimeofday(&start, nullptr);
}
IOState state;
return;
}
else if (state == IOState::NeedRead) {
- int result = waitForData(d_socket, remainingTime);
+ int result = waitForData(d_socket, remainingTime.tv_sec, remainingTime.tv_usec);
if (result <= 0) {
throw std::runtime_error("Error reading from TLS connection: " + std::to_string(result));
}
}
else if (state == IOState::NeedWrite) {
- int result = waitForRWData(d_socket, false, remainingTime, 0);
+ int result = waitForRWData(d_socket, false, remainingTime.tv_sec, remainingTime.tv_usec);
if (result <= 0) {
throw std::runtime_error("Error reading from TLS connection: " + std::to_string(result));
}
}
- if (timeout) {
- time_t now = time(nullptr);
- unsigned int elapsed = now - start;
- if (now < start || elapsed >= remainingTime) {
+ if (timeout.tv_sec != 0 || timeout.tv_usec != 0) {
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ struct timeval elapsed = now - start;
+ if (now < start || remainingTime < elapsed) {
throw runtime_error("Timeout while establishing TLS connection");
}
start = now;
- remainingTime -= elapsed;
+ remainingTime = remainingTime - elapsed;
}
}
while (state != IOState::Done);
return IOState::Done;
}
- size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout) override
+ size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout) override
{
size_t got = 0;
- time_t start = 0;
- unsigned int remainingTime = totalTimeout;
- if (totalTimeout) {
- start = time(nullptr);
+ struct timeval start{0,0};
+ struct timeval remainingTime = totalTimeout;
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ gettimeofday(&start, nullptr);
}
do {
throw std::runtime_error("Fatal error reading from TLS connection: " + std::string(gnutls_strerror(res)));
}
else if (res == GNUTLS_E_AGAIN) {
- int result = waitForData(d_socket, readTimeout);
+ int result = waitForData(d_socket, readTimeout.tv_sec, readTimeout.tv_usec);
if (result <= 0) {
throw std::runtime_error("Error while waiting to read from TLS connection: " + std::to_string(result));
}
}
}
- if (totalTimeout) {
- time_t now = time(nullptr);
- unsigned int elapsed = now - start;
- if (now < start || elapsed >= remainingTime) {
+ if (totalTimeout.tv_sec != 0 || totalTimeout.tv_usec != 0) {
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ struct timeval elapsed = now - start;
+ if (now < start || remainingTime < elapsed) {
throw runtime_error("Timeout while reading data");
}
start = now;
- remainingTime -= elapsed;
+ remainingTime = remainingTime - elapsed;
}
}
while (got < bufferSize);
return got;
}
- size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) override
+ size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout) override
{
size_t got = 0;
throw std::runtime_error("Fatal error writing to TLS connection: " + std::string(gnutls_strerror(res)));
}
else if (res == GNUTLS_E_AGAIN) {
- int result = waitForRWData(d_socket, false, writeTimeout, 0);
+ int result = waitForRWData(d_socket, false, writeTimeout.tv_sec, writeTimeout.tv_usec);
if (result <= 0) {
throw std::runtime_error("Error waiting to write to TLS connection: " + std::to_string(result));
}
}
}
- std::unique_ptr<TLSConnection> getConnection(int socket, unsigned int timeout, time_t now) override
+ std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) override
{
handleTicketsKeyRotation(now);
return std::make_unique<GnuTLSConnection>(socket, timeout, d_creds.get(), d_priorityCache, ticketsKey, d_enableTickets);
}
- std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, unsigned int timeout) override
+ std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) override
{
return std::make_unique<GnuTLSConnection>(host, socket, timeout, d_creds.get(), d_priorityCache, d_validateCerts);
}
virtual ~TLSConnection() { }
virtual void doHandshake() = 0;
virtual IOState tryConnect(bool fastOpen, const ComboAddress& remote) = 0;
- virtual void connect(bool fastOpen, const ComboAddress& remote, unsigned int timeout) = 0;
+ virtual void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout) = 0;
virtual IOState tryHandshake() = 0;
- virtual size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0) = 0;
- virtual size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout) = 0;
+ virtual size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout={0,0}) = 0;
+ virtual size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout) = 0;
virtual IOState tryWrite(const PacketBuffer& buffer, size_t& pos, size_t toWrite) = 0;
virtual IOState tryRead(PacketBuffer& buffer, size_t& pos, size_t toRead) = 0;
virtual bool hasBufferedData() const = 0;
d_rotatingTicketsKey.clear();
}
virtual ~TLSCtx() {}
- virtual std::unique_ptr<TLSConnection> getConnection(int socket, unsigned int timeout, time_t now) = 0;
- virtual std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, unsigned int timeout) = 0;
+ virtual std::unique_ptr<TLSConnection> getConnection(int socket, const struct timeval& timeout, time_t now) = 0;
+ virtual std::unique_ptr<TLSConnection> getClientConnection(const std::string& host, int socket, const struct timeval& timeout) = 0;
virtual void rotateTicketsKey(time_t now) = 0;
virtual void loadTicketsKeys(const std::string& file)
{
public:
enum class Type { Client, Server };
- TCPIOHandler(const std::string& host, int socket, unsigned int timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
+ TCPIOHandler(const std::string& host, int socket, const struct timeval& timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
{
if (ctx) {
d_conn = ctx->getClientConnection(host, d_socket, timeout);
}
}
- TCPIOHandler(int socket, unsigned int timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
+ TCPIOHandler(int socket, const struct timeval& timeout, std::shared_ptr<TLSCtx> ctx, time_t now): d_socket(socket)
{
if (ctx) {
d_conn = ctx->getConnection(d_socket, timeout, now);
d_fastOpen = true;
}
else {
- SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ 0);
+ SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
}
#else
- SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ 0);
+ SConnectWithTimeout(d_socket, remote, /* no timeout, we will handle it ourselves */ timeval{0,0});
#endif /* MSG_FASTOPEN */
if (d_conn) {
return IOState::Done;
}
- void connect(bool fastOpen, const ComboAddress& remote, unsigned int timeout)
+ void connect(bool fastOpen, const ComboAddress& remote, const struct timeval& timeout)
{
d_remote = remote;
return IOState::Done;
}
- size_t read(void* buffer, size_t bufferSize, unsigned int readTimeout, unsigned int totalTimeout=0)
+ size_t read(void* buffer, size_t bufferSize, const struct timeval& readTimeout, const struct timeval& totalTimeout = {0,0})
{
if (d_conn) {
return d_conn->read(buffer, bufferSize, readTimeout, totalTimeout);
return IOState::Done;
}
- size_t write(const void* buffer, size_t bufferSize, unsigned int writeTimeout)
+ size_t write(const void* buffer, size_t bufferSize, const struct timeval& writeTimeout)
{
if (d_conn) {
return d_conn->write(buffer, bufferSize, writeTimeout);
yarl.initialize(&req);
client->setNonBlocking();
- const int timeout = (g_networkTimeoutMsec + 999) / 1000; // XXX tcpiohandler's unit is seconds
+ const struct timeval timeout{g_networkTimeoutMsec / 1000, g_networkTimeoutMsec % 1000 * 1000};
std::shared_ptr<TLSCtx> tlsCtx{nullptr};
auto handler = std::make_shared<TCPIOHandler>("", client->releaseHandle(), timeout, tlsCtx, time(nullptr));