From afca13556a4c112f1d43b754b0647ecf0406c9ee Mon Sep 17 00:00:00 2001 From: JJL772 Date: Tue, 12 Dec 2023 16:23:28 -0800 Subject: [PATCH] clientContextImpl: Cap the number and age of beacons Each beacon has an associated mutex. If we allocate too many beacons on resource constrained systems, i.e. RTEMS, we may run out of resources and crash. --- src/remoteClient/clientContextImpl.cpp | 41 ++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index eff79d4a..780a0b6a 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -49,6 +49,9 @@ using std::tr1::static_pointer_cast; using namespace std; using namespace epics::pvData; +static const float maxBeaconLifetime = 180.f * 2.f; +static const int maxTrackedBeacons = 20000; + namespace epics { namespace pvAccess { @@ -4338,6 +4341,34 @@ class InternalClientContextImpl : m_channelSearchManager->newServerDetected(); } + /** + * Handles cleanup of old beacons. + */ + class BeaconCleanupCallback : public TimerCallback + { + public: + BeaconCleanupCallback(InternalClientContextImpl& impl, osiSockAddr addr) : + m_from(addr), + m_impl(impl) + { + } + + virtual void callback() OVERRIDE + { + Lock guard(m_impl.m_beaconMapMutex); + m_impl.m_beaconHandlers.erase(m_from); + } + + virtual void timerStopped() OVERRIDE + { + this->callback(); // Remove the beacon if the timer is closed. + } + + private: + osiSockAddr m_from; + InternalClientContextImpl& m_impl; + }; + /** * Get (and if necessary create) beacon handler. * @param protocol the protocol. @@ -4351,8 +4382,18 @@ class InternalClientContextImpl : BeaconHandler::shared_pointer handler; if (it == m_beaconHandlers.end()) { + // If we're tracking too many beacons, we'll just ignore this one + if (m_beaconHandlers.size() >= maxTrackedBeacons) + { + char ipa[64]; + sockAddrToDottedIP(&responseFrom->sa, ipa, sizeof(ipa)); + LOG(logLevelDebug, "Tracked beacon limit reached (%d), ignoring %s\n", maxTrackedBeacons, ipa); + return nullptr; + } + // stores weak_ptr handler.reset(new BeaconHandler(internal_from_this(), responseFrom)); + m_timer->scheduleAfterDelay(std::make_shared(*this, *responseFrom), maxBeaconLifetime); m_beaconHandlers[*responseFrom] = handler; } else