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