Skip to content

Commit 524de5b

Browse files
Detect client-side shutdown of TLS stream
1 parent af78ca0 commit 524de5b

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

lib/remote/httpserverconnection.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ HttpServerConnection::HttpServerConnection(const WaitGroup::Ptr& waitGroup, cons
4141
}
4242

4343
HttpServerConnection::HttpServerConnection(const WaitGroup::Ptr& waitGroup, const String& identity, bool authenticated, const Shared<AsioTlsStream>::Ptr& stream, boost::asio::io_context& io)
44-
: m_WaitGroup(waitGroup), m_Stream(stream), m_Seen(Utility::GetTime()), m_IoStrand(io), m_ShuttingDown(false), m_CheckLivenessTimer(io)
44+
: m_WaitGroup(waitGroup), m_Stream(stream), m_Seen(Utility::GetTime()), m_CanRead(io, true), m_IoStrand(io), m_ShuttingDown(false), m_CheckLivenessTimer(io)
4545
{
4646
if (authenticated) {
4747
m_ApiUser = ApiUser::GetByClientCN(identity);
@@ -65,6 +65,7 @@ void HttpServerConnection::Start()
6565

6666
IoEngine::SpawnCoroutine(m_IoStrand, [this, keepAlive](asio::yield_context yc) { ProcessMessages(yc); });
6767
IoEngine::SpawnCoroutine(m_IoStrand, [this, keepAlive](asio::yield_context yc) { CheckLiveness(yc); });
68+
IoEngine::SpawnCoroutine(m_IoStrand, [this, keepAlive](asio::yield_context yc) { DetectClientShutdown(yc); });
6869
}
6970

7071
/**
@@ -418,6 +419,7 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
418419

419420
response.set(http::field::server, l_ServerHeader);
420421

422+
m_CanRead.WaitForSet(yc);
421423
if (!EnsureValidHeaders(buf, request, response, m_ShuttingDown, yc)) {
422424
break;
423425
}
@@ -476,6 +478,7 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
476478
}
477479

478480
m_Seen = std::numeric_limits<decltype(m_Seen)>::max();
481+
m_CanRead.Clear();
479482

480483
if (!ProcessRequest(request, response, m_WaitGroup, cpuBoundWorkTime, yc)) {
481484
break;
@@ -516,3 +519,27 @@ void HttpServerConnection::CheckLiveness(boost::asio::yield_context yc)
516519
}
517520
}
518521
}
522+
523+
/**
524+
* Detects a shutdown initiated by the client side.
525+
*
526+
* @param yc The yield context for the coroutine of this function
527+
*/
528+
void HttpServerConnection::DetectClientShutdown(boost::asio::yield_context yc)
529+
{
530+
using wait_type = boost::asio::socket_base::wait_type;
531+
532+
while (!m_ShuttingDown) {
533+
m_CanRead.WaitForClear(yc);
534+
535+
boost::system::error_code ec;
536+
m_Stream->async_fill(yc[ec]);
537+
if (ec && !m_ShuttingDown) {
538+
Log(LogInformation, "HttpServerConnection") << "Detected shutdown from client: " << m_PeerAddress << ".";
539+
Disconnect(yc);
540+
break;
541+
}
542+
543+
m_CanRead.Set();
544+
}
545+
}

lib/remote/httpserverconnection.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#define HTTPSERVERCONNECTION_H
55

66
#include "remote/apiuser.hpp"
7+
#include "base/io-engine.hpp"
78
#include "base/string.hpp"
89
#include "base/tlsstream.hpp"
910
#include "base/wait-group.hpp"
@@ -37,6 +38,7 @@ class HttpServerConnection final : public Object
3738
ApiUser::Ptr m_ApiUser;
3839
Shared<AsioTlsStream>::Ptr m_Stream;
3940
double m_Seen;
41+
AsioDualEvent m_CanRead;
4042
String m_PeerAddress;
4143
boost::asio::io_context::strand m_IoStrand;
4244
bool m_ShuttingDown;
@@ -49,6 +51,7 @@ class HttpServerConnection final : public Object
4951

5052
void ProcessMessages(boost::asio::yield_context yc);
5153
void CheckLiveness(boost::asio::yield_context yc);
54+
void DetectClientShutdown(boost::asio::yield_context yc);
5255
};
5356

5457
}

0 commit comments

Comments
 (0)