// limitations under the License.
//
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
#include "RCSDiscoveryManagerImpl.h"
#include "OCPlatform.h"
-
#include "PresenceSubscriber.h"
#include "RCSAddressDetail.h"
#include "RCSAddress.h"
+#include "RCSRemoteResourceObject.h"
+
+namespace
+{
+ constexpr unsigned int POLLING_INTERVAL_TIME = 60000;
+
+ std::string makeResourceId(const std::shared_ptr< OIC::Service::PrimitiveResource >& resource)
+ {
+ return resource->getSid() + resource->getUri();
+ }
+
+ void validateTypes(const std::vector< std::string >& resourceTypes) {
+ if (resourceTypes.size() == 1) return;
-constexpr unsigned int RESETNUMBER = 0;
-constexpr unsigned int LIMITNUMBER = 1000;
-constexpr unsigned int INTERVALTIME = 60000;
+ for (const auto& type : resourceTypes)
+ {
+ if (type == OIC::Service::RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE)
+ {
+ throw OIC::Service::RCSBadRequestException{
+ "resource types must have no empty string!" };
+ }
+ }
+ }
+}
namespace OIC
{
namespace Service
{
- unsigned int RCSDiscoveryManagerImpl::s_uniqueId = RESETNUMBER;
- RCSDiscoveryManagerImpl * RCSDiscoveryManagerImpl::s_instance(nullptr);
- std::mutex RCSDiscoveryManagerImpl::s_mutexForCreation;
+ constexpr RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::INVALID_ID;
+ constexpr char const* RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE;
+
+ RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
+ {
+ subscribePresenceWithMulticast();
- RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl() : m_timerHandle(0){}
+ m_timer.post(POLLING_INTERVAL_TIME,
+ std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
+ }
RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
{
- if (!s_instance)
- {
- s_mutexForCreation.lock();
- if (!s_instance)
- {
- s_instance = new RCSDiscoveryManagerImpl();
- srand(time(NULL));
- s_instance->initializedDiscoveryEnvironment();
- s_instance->requestMulticastPresence();
- s_instance->m_timerHandle = s_instance->m_timer.post(INTERVALTIME, s_instance->m_pollingCB);
- }
- s_mutexForCreation.unlock();
- }
- return s_instance;
+ static RCSDiscoveryManagerImpl instance;
+ return &instance;
}
- void RCSDiscoveryManagerImpl::findCallback(std::shared_ptr< PrimitiveResource > resource,
- RCSDiscoveryManagerImpl::ID discoverID)
+ void RCSDiscoveryManagerImpl::onResourceFound(
+ std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
+ const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
{
- std::lock_guard<std::mutex> lock(m_mutex);
-
- if(!isDuplicatedCallback(resource,discoverID))
{
- for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
- {
- if(it->first == discoverID)
- {
- it->second.m_isReceivedFindCallback = true;
- it->second.m_discoverCB(std::make_shared<RCSRemoteResourceObject>(resource));
- }
- }
+ std::lock_guard < std::mutex > lock(m_mutex);
+ auto it = m_discoveryMap.find(discoveryId);
+
+ if (it == m_discoveryMap.end()) return;
+ if (it->second.isKnownResource(resource)) return;
+
+ it->second.addKnownResource(resource);
}
+ discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
}
- std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> RCSDiscoveryManagerImpl::startDiscovery
- (const RCSAddress& address, const std::string& relativeURI, const std::string& resourceType,
+ RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
+ const RCSAddress& address, const std::string& relativeUri,
+ const std::vector< std::string >& resourceTypes,
RCSDiscoveryManager::ResourceDiscoveredCallback cb)
{
if (!cb)
{
- throw RCSInvalidParameterException { "input Parameter(callback) is NULL" };
+ throw RCSInvalidParameterException{ "Callback is empty" };
}
- DiscoverRequestInfo discoveryItem;
- discoveryItem.m_address = RCSAddressDetail::getDetail(address)->getAddress();
- discoveryItem.m_relativeUri = relativeURI;
- discoveryItem.m_resourceType = resourceType;
- discoveryItem.m_discoverCB = std::move(cb);
- discoveryItem.m_isReceivedFindCallback = false;
+ validateTypes(resourceTypes);
- ID discoverID = createId();
- discoveryItem.m_findCB = std::bind(&RCSDiscoveryManagerImpl::findCallback, this,
- std::placeholders::_1, discoverID);
- m_discoveryMap.insert(std::make_pair(discoverID, discoveryItem));
+ const ID discoveryId = createId();
- OIC::Service::discoverResource(RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress(),
- discoveryItem.m_relativeUri + "?rt=" +discoveryItem.m_resourceType,
- OCConnectivityType::CT_DEFAULT, discoveryItem.m_findCB);
+ DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceTypes,
+ std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
+ std::placeholders::_1, discoveryId, std::move(cb)));
- return std::unique_ptr<RCSDiscoveryManager::DiscoveryTask>(
- new RCSDiscoveryManager::DiscoveryTask(discoverID));
- }
+ discoveryInfo.discover();
- void RCSDiscoveryManagerImpl::initializedDiscoveryEnvironment()
- {
- m_presenceCB = std::bind(&RCSDiscoveryManagerImpl::presenceCallback, this,
- std::placeholders::_1, std::placeholders::_2,std::placeholders::_3);
- m_pollingCB = std::bind(&RCSDiscoveryManagerImpl::pollingCallback, this,
- std::placeholders::_1);
+ {
+ std::lock_guard < std::mutex > lock(m_mutex);
+ m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
+ }
+
+ return std::unique_ptr< RCSDiscoveryManager::DiscoveryTask >(
+ new RCSDiscoveryManager::DiscoveryTask(discoveryId));
}
- void RCSDiscoveryManagerImpl::requestMulticastPresence()
+ void RCSDiscoveryManagerImpl::subscribePresenceWithMulticast()
{
- static constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
+ using namespace std::placeholders;
+
+ constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
+
OCDoHandle presenceHandle;
subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
- OCConnectivityType::CT_DEFAULT, std::move(m_presenceCB));
+ OCConnectivityType::CT_DEFAULT,
+ std::bind(&RCSDiscoveryManagerImpl::onPresence, this, _1, _2, _3));
}
- bool RCSDiscoveryManagerImpl::isDuplicatedCallback(std::shared_ptr< PrimitiveResource > resource,
- ID discoverID)
+ void RCSDiscoveryManagerImpl::onPolling()
{
- std::string retID = resource->getSid()+resource->getUri();
- auto it = m_discoveryMap.find(discoverID);
- std::list<std::string>::iterator itor;
- if(it==m_discoveryMap.end())
{
- return false;
- }
- itor = std::find(it->second.m_receivedIds.begin(),it->second.m_receivedIds.end(),retID);
- if(itor != it->second.m_receivedIds.end())
- {
- return true;
- }
- it->second.m_receivedIds.push_back(retID);
-
- return false;
- }
+ std::lock_guard < std::mutex > lock(m_mutex);
- void RCSDiscoveryManagerImpl::pollingCallback(unsigned int /*msg*/)
- {
- std::lock_guard<std::mutex> lock(m_mutex);
- for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
- {
- OIC::Service::discoverResource(it->second.m_address,it->second.m_relativeUri+ "?rt="
- +it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
+ for (const auto& it : m_discoveryMap)
+ {
+ it.second.discover();
+ }
}
- m_timerHandle = m_timer.post(INTERVALTIME, m_pollingCB);
+ m_timer.post(POLLING_INTERVAL_TIME,
+ std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
}
- void RCSDiscoveryManagerImpl::presenceCallback(OCStackResult ret,
- const unsigned int /*seq*/, const std::string& /*address*/)
+ void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
+ const std::string& address)
{
- if(ret == OC_STACK_OK || ret == OC_STACK_RESOURCE_CREATED || ret == OC_STACK_RESOURCE_DELETED)
+ if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
+
+ std::lock_guard < std::mutex > lock(m_mutex);
+ for (const auto& it : m_discoveryMap)
{
- std::lock_guard<std::mutex> lock(m_mutex);
- for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
+ if (it.second.isMatchedAddress(address))
{
- if(!it->second.m_isReceivedFindCallback)
- {
- OIC::Service::discoverResource(it->second.m_address, it->second.m_relativeUri+ "?rt=" +
- it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
- }
+ it.second.discover();
}
}
}
- RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
+ RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId() const
{
- std::lock_guard<std::mutex> lock(m_mutex);
- if(s_uniqueId<LIMITNUMBER)
+ static ID s_nextId = INVALID_ID + 1;
+
+ std::lock_guard < std::mutex > lock(m_mutex);
+
+ while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
{
- s_uniqueId++;
+ ++s_nextId;
}
- else
+
+ assert(s_nextId != INVALID_ID && "Invalid ID!");
+
+ return s_nextId++;
+ }
+
+ void RCSDiscoveryManagerImpl::cancel(ID id)
+ {
+ std::lock_guard < std::mutex > lock(m_mutex);
+ m_discoveryMap.erase(id);
+ }
+
+ DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
+ const std::string& relativeUri, const std::vector< std::string >& resourceTypes,
+ DiscoverCallback cb) :
+ m_address{ address },
+ m_relativeUri{ relativeUri },
+ m_resourceTypes{ resourceTypes },
+ m_knownResourceIds{ },
+ m_discoverCb{ std::move(cb) }
+ {
+ if (m_resourceTypes.empty())
{
- s_uniqueId = RESETNUMBER;
+ m_resourceTypes.push_back(RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE);
}
- while(m_discoveryMap.size() != LIMITNUMBER)
+ }
+
+ void DiscoveryRequestInfo::discover() const
+ {
+ for (const auto& it : m_resourceTypes)
{
- if(m_discoveryMap.find(s_uniqueId) == m_discoveryMap.end())
+ std::string uri = std::string(OC_RSRVD_WELL_KNOWN_URI);
+ if (!it.empty())
{
- return s_uniqueId;
+ uri = std::string(OC_RSRVD_WELL_KNOWN_URI) + "?rt=" + it;
}
- s_uniqueId++;
+ discoverResource(m_address, uri, m_discoverCb);
}
+ }
- return RESETNUMBER;
+ bool DiscoveryRequestInfo::isKnownResource(
+ const std::shared_ptr< PrimitiveResource >& resource) const
+ {
+ return m_knownResourceIds.find(makeResourceId(resource)) != m_knownResourceIds.end();
}
- void RCSDiscoveryManagerImpl::cancel(ID id)
+ void DiscoveryRequestInfo::addKnownResource(
+ const std::shared_ptr< PrimitiveResource >& resource)
{
- std::lock_guard<std::mutex> lock(m_mutex);
- m_discoveryMap.erase(id);
+ m_knownResourceIds.insert(makeResourceId(resource));
+ }
+
+ bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
+ {
+ return RCSAddressDetail::getDetail(m_address)->isMulticast()
+ || RCSAddressDetail::getDetail(m_address)->getAddress() == address;
}
}
}