}
}
-bool Stream::WaitForData(int timeout)
+bool Stream::WaitForData()
{
if (!SupportsWaiting())
BOOST_THROW_EXCEPTION(std::runtime_error("Stream does not support waiting."));
boost::mutex::scoped_lock lock(m_Mutex);
while (!IsDataAvailable() && !IsEof())
- if (timeout < 0)
- m_CV.wait(lock);
- else
- m_CV.timed_wait(lock, boost::posix_time::milliseconds(timeout * 1000));
+ m_CV.wait(lock);
+
+ return IsDataAvailable() || IsEof();
+}
+
+bool Stream::WaitForData(int timeout)
+{
+ if (!SupportsWaiting())
+ BOOST_THROW_EXCEPTION(std::runtime_error("Stream does not support waiting."));
+
+ if (timeout < 0)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Timeout can't be negative"));
+
+ boost::system_time const point_of_timeout = boost::get_system_time() + boost::posix_time::seconds(timeout);
+
+ boost::mutex::scoped_lock lock(m_Mutex);
+
+ while (!IsDataAvailable() && !IsEof() && point_of_timeout > boost::get_system_time())
+ m_CV.timed_wait(lock, point_of_timeout);
return IsDataAvailable() || IsEof();
}
/**
* Waits until data can be read from the stream.
+ * Optionally with a timeout.
*/
- bool WaitForData(int timeout = -1);
+ bool WaitForData();
+ bool WaitForData(int timeout);
virtual bool SupportsWaiting() const;
# include <poll.h>
#endif /* _WIN32 */
+#define TLS_TIMEOUT_SECONDS 10
+#define TLS_TIMEOUT_STEP_SECONDS 1
+
using namespace icinga;
int TlsStream::m_SSLIndex;
m_CurrentAction = TlsActionHandshake;
ChangeEvents(POLLOUT);
- while (!m_HandshakeOK && !m_ErrorOccurred && !m_Eof)
- m_CV.wait(lock);
+ boost::system_time const timeout = boost::get_system_time() + boost::posix_time::seconds(TLS_TIMEOUT_SECONDS);
+
+ while (!m_HandshakeOK && !m_ErrorOccurred && !m_Eof && timeout > boost::get_system_time())
+ m_CV.timed_wait(lock, timeout);
+
+ // We should _NOT_ (underline, bold, itallic and wordart) throw an exception for a timeout.
+ if (timeout < boost::get_system_time())
+ BOOST_THROW_EXCEPTION(std::runtime_error("Timeout during handshake."));
if (m_Eof)
BOOST_THROW_EXCEPTION(std::runtime_error("Socket was closed during TLS handshake."));
JsonRpc::SendMessage(tlsStream, message);
ctype = ClientJsonRpc;
} else {
- tlsStream->WaitForData(5);
+ tlsStream->WaitForData(10);
if (!tlsStream->IsDataAvailable()) {
- Log(LogWarning, "ApiListener")
- << "No data received on new API connection for identity '" << identity << "'. Ensure that the remote endpoints are properly configured in a cluster setup.";
+ if (identity.IsEmpty())
+ Log(LogInformation, "ApiListener")
+ << "No data received on new API connection. "
+ << "Ensure that the remote endpoints are properly configured in a cluster setup.";
+ else
+ Log(LogWarning, "ApiListener")
+ << "No data received on new API connection for identity '" << identity << "'. "
+ << "Ensure that the remote endpoints are properly configured in a cluster setup.";
return;
}
{
l_HttpServerConnectionTimeoutTimer = new Timer();
l_HttpServerConnectionTimeoutTimer->OnTimerExpired.connect(std::bind(&HttpServerConnection::TimeoutTimerHandler));
- l_HttpServerConnectionTimeoutTimer->SetInterval(15);
+ l_HttpServerConnectionTimeoutTimer->SetInterval(5);
l_HttpServerConnectionTimeoutTimer->Start();
}
void HttpServerConnection::Disconnect()
{
+ boost::mutex::scoped_try_lock lock(m_DataHandlerMutex);
+ if (!lock.owns_lock()) {
+ Log(LogInformation, "HttpServerConnection", "Unable to disconnect Http client, I/O thread busy");
+ return;
+ }
+
Log(LogDebug, "HttpServerConnection", "Http client disconnected");
ApiListener::Ptr listener = ApiListener::GetInstance();
try {
stream->Handshake();
- } catch (...) {
-
+ } catch (const std::exception& ex) {
+ Log(LogCritical, "pki")
+ << "Client TLS handshake failed. (" << ex.what() << ")";
+ return std::shared_ptr<X509>();
}
return stream->GetPeerCertificate();