Skip to content
Open
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
112 changes: 47 additions & 65 deletions lib/remote/apilistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,16 +748,6 @@ void ApiListener::NewClientHandlerInternal(
return;
}

Defer shutdownSslConn ([&sslConn, &yc]() {
// Ignore the error, but do not throw an exception being swallowed at all cost.
// https://github.com/Icinga/icinga2/issues/7351
boost::system::error_code ec;

// Using async_shutdown() instead of AsioTlsStream::GracefulDisconnect() as this whole function
// is already guarded by a timeout based on the connect timeout.
sslConn.async_shutdown(yc[ec]);
});

std::shared_ptr<X509> cert (sslConn.GetPeerCertificate());
bool verify_ok = false;
String identity;
Expand Down Expand Up @@ -809,8 +799,46 @@ void ApiListener::NewClientHandlerInternal(

ClientType ctype;

try {
if (role == RoleClient) {
if (role == RoleClient) {
JsonRpc::SendMessage(client, new Dictionary({
{ "jsonrpc", "2.0" },
{ "method", "icinga::Hello" },
{ "params", new Dictionary({
{ "version", (double)l_AppVersionInt },
{ "capabilities", (double)ApiCapabilities::MyCapabilities }
}) }
}), yc);

client->async_flush(yc);

ctype = ClientJsonRpc;
} else {
{
boost::system::error_code ec;

if (client->async_fill(yc[ec]) == 0u) {
if (identity.IsEmpty()) {
Log(LogInformation, "ApiListener")
<< "No data received on new API connection " << conninfo << ": " << ec.message()
<< ". Ensure that the remote endpoints are properly configured in a cluster setup.";
} else {
Log(LogWarning, "ApiListener")
<< "No data received on new API connection " << conninfo << " for identity '" << identity << "': " << ec.message()
<< ". Ensure that the remote endpoints are properly configured in a cluster setup.";
}

return;
}
}

char firstByte = 0;

{
asio::mutable_buffer firstByteBuf (&firstByte, 1);
client->peek(firstByteBuf);
}

if (firstByte >= '0' && firstByte <= '9') {
JsonRpc::SendMessage(client, new Dictionary({
{ "jsonrpc", "2.0" },
{ "method", "icinga::Hello" },
Expand All @@ -824,54 +852,8 @@ void ApiListener::NewClientHandlerInternal(

ctype = ClientJsonRpc;
} else {
{
boost::system::error_code ec;

if (client->async_fill(yc[ec]) == 0u) {
if (identity.IsEmpty()) {
Log(LogInformation, "ApiListener")
<< "No data received on new API connection " << conninfo << ": " << ec.message()
<< ". Ensure that the remote endpoints are properly configured in a cluster setup.";
} else {
Log(LogWarning, "ApiListener")
<< "No data received on new API connection " << conninfo << " for identity '" << identity << "': " << ec.message()
<< ". Ensure that the remote endpoints are properly configured in a cluster setup.";
}

return;
}
}

char firstByte = 0;

{
asio::mutable_buffer firstByteBuf (&firstByte, 1);
client->peek(firstByteBuf);
}

if (firstByte >= '0' && firstByte <= '9') {
JsonRpc::SendMessage(client, new Dictionary({
{ "jsonrpc", "2.0" },
{ "method", "icinga::Hello" },
{ "params", new Dictionary({
{ "version", (double)l_AppVersionInt },
{ "capabilities", (double)ApiCapabilities::MyCapabilities }
}) }
}), yc);

client->async_flush(yc);

ctype = ClientJsonRpc;
} else {
ctype = ClientHttp;
}
}
} catch (const boost::system::system_error& systemError) {
if (systemError.code() == boost::asio::error::operation_aborted) {
shutdownSslConn.Cancel();
ctype = ClientHttp;
}

throw;
}

std::shared_lock wgLock(*m_ListenerWaitGroup, std::try_to_lock);
Expand Down Expand Up @@ -910,20 +892,20 @@ void ApiListener::NewClientHandlerInternal(
<< "Ignoring anonymous JSON-RPC connection " << conninfo
<< ". Max connections (" << GetMaxAnonymousClients() << ") exceeded.";

aclient = nullptr;
}
// Close the connection cleanly, signals the other endpoint
// that the connection didn't break but was closed intentionally.
client->GracefulDisconnect(*strand, yc);

if (aclient) {
aclient->Start();
shutdownSslConn.Cancel();
return;
}

aclient->Start();
} else {
Log(LogNotice, "ApiListener", "New HTTP client");

HttpServerConnection::Ptr aclient = new HttpServerConnection(m_WaitGroup, identity, verify_ok, client);
AddHttpClient(aclient);
aclient->Start();
shutdownSslConn.Cancel();
}
}

Expand Down
Loading