Skip to content

Commit

Permalink
clientContextImpl: Cap the number and age of beacons
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JJL772 committed Dec 13, 2023
1 parent cf483d6 commit afca135
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions src/remoteClient/clientContextImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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.
Expand All @@ -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<BeaconCleanupCallback>(*this, *responseFrom), maxBeaconLifetime);
m_beaconHandlers[*responseFrom] = handler;
}
else
Expand Down

0 comments on commit afca135

Please sign in to comment.