#include <memory>
#include <functional>
+#include <vector>
namespace OIC
{
const std::string& resourceType, ResourceDiscoveredCallback cb);
/**
- * Discovers resources of interest by resource type with provided relativeUri.
+ * Discovers resources of interest by resource type.
+ * It is Consistently discovering resources until the discovery task is canceled.
+ *
+ * @param address A RCSAddress object
+ * @param resourceTypes List of Resource Types
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ * @throws InvalidParameterException If resourceType's size is than 2,
+ * at least one of resource type is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ * @note If resourceTypes is empty, discovers resource by all resource types.
+ *
+ */
+ DiscoveryTask::Ptr discoverResourceByTypes(const RCSAddress& address,
+ const std::vector< std::string >& resourceTypes,
+ ResourceDiscoveredCallback cb);
+
+ /**
+ * Discovers resources of interest by resource types with provided relativeUri.
* It is Consistently discovering resources until the discovery task is canceled.
*
* @param address A RCSAddress object
const std::string& relativeUri, const std::string& resourceType,
ResourceDiscoveredCallback cb);
+ /**
+ * Discovers resources of interest by resource types with provided relativeUri.
+ * It is Consistently discovering resources until the discovery task is canceled.
+ *
+ * @param address A RCSAddress object
+ * @param relativeUri The relative uri of resource to be searched
+ * @param resourceTypes List of Resource Types
+ * @param cb A callback to obtain discovered resource
+ *
+ * @throws InvalidParameterException If cb is empty.
+ * @throws InvalidParameterException If resourceType's size is than 2,
+ * at least one of resource type is empty.
+ *
+ * @note The callback will be invoked in an internal thread.
+ * @note If resourceTypes is empty, discovers resource by all resource types.
+ *
+ */
+ DiscoveryTask::Ptr discoverResourceByTypes(const RCSAddress& address,
+ const std::string& relativeUri,
+ const std::vector< std::string >& resourceTypes,
+ ResourceDiscoveredCallback cb);
+
private:
+
RCSDiscoveryManager() = default;
~RCSDiscoveryManager() = default;
};
#include "RCSDiscoveryManagerImpl.h"
+namespace
+{
+ constexpr char ALL_RESOURCE_TYPES[] = "";
+}
+
namespace OIC
{
namespace Service
RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResource(
const RCSAddress& address, ResourceDiscoveredCallback cb)
{
- return discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, "", std::move(cb));
+ return discoverResourceByType(address, OC_RSRVD_WELL_KNOWN_URI, ALL_RESOURCE_TYPES,
+ std::move(cb));
}
RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResource(
const RCSAddress& address, const std::string& relativeUri,
ResourceDiscoveredCallback cb)
{
- return discoverResourceByType(address, relativeUri, "", std::move(cb));
+ return discoverResourceByType(address, relativeUri, ALL_RESOURCE_TYPES, std::move(cb));
}
RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByType(
std::move(cb));
}
+ RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByTypes(
+ const RCSAddress& address, const std::vector< std::string >& resourceTypes,
+ ResourceDiscoveredCallback cb)
+ {
+ return discoverResourceByTypes(address, OC_RSRVD_WELL_KNOWN_URI, resourceTypes,
+ std::move(cb));
+ }
+
RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByType(
const RCSAddress& address, const std::string& relativeUri,
const std::string& resourceType, ResourceDiscoveredCallback cb)
{
+ return discoverResourceByTypes(address,
+ relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri,
+ std::vector< std::string >
+ { resourceType }, std::move(cb));
+ }
+
+ RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManager::discoverResourceByTypes(
+ const RCSAddress& address, const std::string& relativeUri,
+ const std::vector< std::string >& resourceTypes, ResourceDiscoveredCallback cb)
+ {
return RCSDiscoveryManagerImpl::getInstance()->startDiscovery(address,
- relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri, resourceType,
+ relativeUri.empty() ? OC_RSRVD_WELL_KNOWN_URI : relativeUri, resourceTypes,
std::move(cb));
}
}
namespace
{
+ constexpr char ALL_RESOURCE_TYPE[] = "";
constexpr unsigned int POLLING_INTERVAL_TIME = 60000;
std::string makeResourceId(const std::shared_ptr< OIC::Service::PrimitiveResource >& resource)
{
subscribePresenceWithMuticast();
- m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
+ m_timer.post(POLLING_INTERVAL_TIME,
+ std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
}
RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
return &instance;
}
- void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr<PrimitiveResource> resource,
- ID discoveryId, const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
+ void RCSDiscoveryManagerImpl::onResourceFound(
+ std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
+ const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
{
{
- std::lock_guard< std::mutex > lock(m_mutex);
+ std::lock_guard < std::mutex > lock(m_mutex);
auto it = m_discoveryMap.find(discoveryId);
if (it == m_discoveryMap.end()) return;
it->second.addKnownResource(resource);
}
- discoverCB(std::make_shared< RCSRemoteResourceObject > (resource));
+ discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
}
RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
const RCSAddress& address, const std::string& relativeUri,
- const std::string& resourceType, RCSDiscoveryManager::ResourceDiscoveredCallback cb)
+ const std::vector< std::string >& resourceTypes,
+ RCSDiscoveryManager::ResourceDiscoveredCallback cb)
{
if (!cb)
{
throw RCSInvalidParameterException{ "Callback is empty" };
}
+ for(const auto& it : resourceTypes)
+ {
+ if (it.compare(ALL_RESOURCE_TYPE) == 0)
+ {
+ throw RCSInvalidParameterException{ "ResourceType is duplicated!" };
+ }
+ }
+
const ID discoveryId = createId();
- DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceType,
+ DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceTypes,
std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
std::placeholders::_1, discoveryId, std::move(cb)));
+
discoveryInfo.discover();
{
- std::lock_guard< std::mutex > lock(m_mutex);
+ 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));
+ return std::unique_ptr < RCSDiscoveryManager::DiscoveryTask
+ > (new RCSDiscoveryManager::DiscoveryTask(discoveryId));
}
void RCSDiscoveryManagerImpl::subscribePresenceWithMuticast()
void RCSDiscoveryManagerImpl::onPolling()
{
{
- std::lock_guard< std::mutex > lock(m_mutex);
+ std::lock_guard < std::mutex > lock(m_mutex);
for (const auto& it : m_discoveryMap)
{
it.second.discover();
}
}
- m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
+ m_timer.post(POLLING_INTERVAL_TIME,
+ std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
}
void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
{
if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
- std::lock_guard< std::mutex > lock(m_mutex);
+ std::lock_guard < std::mutex > lock(m_mutex);
for (const auto& it : m_discoveryMap)
{
if (it.second.isMatchedAddress(address))
{
static ID s_nextId = INVALID_ID + 1;
- std::lock_guard< std::mutex > lock(m_mutex);
+ std::lock_guard < std::mutex > lock(m_mutex);
while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
{
void RCSDiscoveryManagerImpl::cancel(ID id)
{
- std::lock_guard< std::mutex > lock(m_mutex);
+ std::lock_guard < std::mutex > lock(m_mutex);
m_discoveryMap.erase(id);
}
DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
- const std::string& relativeUri, const std::string& resourceType,
+ const std::string& relativeUri, const std::vector< std::string >& resourceTypes,
DiscoverCallback cb) :
m_address{ address },
m_relativeUri{ relativeUri },
- m_resourceType{ resourceType },
+ m_resourceTypes{ resourceTypes },
m_knownResourceIds{ },
m_discoverCb{ std::move(cb) }
{
+ if (m_resourceTypes.empty())
+ {
+ m_resourceTypes.push_back(ALL_RESOURCE_TYPE);
+ }
}
void DiscoveryRequestInfo::discover() const
{
- discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType, m_discoverCb);
+ for (const auto& it : m_resourceTypes)
+ {
+ discoverResource(m_address, m_relativeUri + "?rt=" + it, m_discoverCb);
+ }
}
bool DiscoveryRequestInfo::isKnownResource(
bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
{
- return RCSAddressDetail::getDetail(m_address)->isMulticast() ||
- RCSAddressDetail::getDetail(m_address)->getAddress() == address;
+ return RCSAddressDetail::getDetail(m_address)->isMulticast()
+ || RCSAddressDetail::getDetail(m_address)->getAddress() == address;
}
}
}
class DiscoveryRequestInfo
{
public:
- DiscoveryRequestInfo(const RCSAddress&, const std::string&, const std::string&,
- DiscoverCallback);
+ DiscoveryRequestInfo(const RCSAddress&, const std::string&,
+ const std::vector< std::string >&, DiscoverCallback);
public:
void discover() const;
private:
RCSAddress m_address;
std::string m_relativeUri;
- std::string m_resourceType;
+ std::vector< std::string > m_resourceTypes;
std::unordered_set< std::string > m_knownResourceIds;
DiscoverCallback m_discoverCb;
};
* @see RCSDiscoveryManager
*/
RCSDiscoveryManager::DiscoveryTask::Ptr startDiscovery(const RCSAddress& address,
- const std::string& relativeURI,const std::string& resourceType,
+ const std::string& relativeURI,
+ const std::vector< std::string >& resourceTypes,
RCSDiscoveryManager::ResourceDiscoveredCallback cb);
void cancel(ID);
*
* @see PrimitiveResource
*/
- void onResourceFound(std::shared_ptr<PrimitiveResource> resource, ID discoveryId,
+ void onResourceFound(std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
const RCSDiscoveryManager::ResourceDiscoveredCallback& cb);
/**
using namespace OC::OCPlatform;
constexpr char RESOURCEURI[]{ "/a/TemperatureSensor" };
+constexpr char SECOND_RESOURCEURI[]{ "/a/Light" };
constexpr char RESOURCETYPE[]{ "resource.type" };
+constexpr char SECOND_RESOURCETYPE[]{ "resource.type.second" };
constexpr char RESOURCEINTERFACE[]{ "oic.if.baseline" };
constexpr int DEFAULT_DISCOVERYTASK_DELAYTIME = 3000;
+int callTimes = 0;
+
+void resourceDiscoveredForTwoTimesCall(RCSRemoteResourceObject::Ptr)
+{
+ callTimes++;
+}
void resourceDiscoveredForCall(RCSRemoteResourceObject::Ptr) {}
void resourceDiscoveredForNeverCall(RCSRemoteResourceObject::Ptr) {}
server = RCSResourceObject::Builder(RESOURCEURI, RESOURCETYPE, RESOURCEINTERFACE).build();
}
+ void createSecondResource()
+ {
+ secondServer = RCSResourceObject::Builder(SECOND_RESOURCEURI, SECOND_RESOURCETYPE, RESOURCEINTERFACE).build();
+ }
+
void proceed()
{
cond.notify_all();
}
+ void proceed_on_condition()
+ {
+ cond.notify_all();
+ if(callTimes != 2)
+ {
+ waitForDiscoveryTask();
+ }
+ }
+
void waitForDiscoveryTask(int waitingTime = DEFAULT_DISCOVERYTASK_DELAYTIME)
{
std::unique_lock< std::mutex > lock{ mutex };
std::condition_variable cond;
std::mutex mutex;
RCSResourceObject::Ptr server;
+ RCSResourceObject::Ptr secondServer;
RCSRemoteResourceObject::Ptr object;
DiscoveryTaskPtr discoveryTask;
};
stopPresence();
}
+TEST_F(DiscoveryManagerTest, discoveryRequestByMultipleResourceTypesAndFindResourcesOfTwoResourceTypes)
+{
+ std::vector<std::string> resourceTypes{RESOURCETYPE, SECOND_RESOURCETYPE};
+ const std::string uri = "/oic/res";
+ callTimes = 0;
+
+ createResource();
+ createSecondResource();
+
+ mocks.ExpectCallFunc(resourceDiscoveredForTwoTimesCall).Do(
+ [this](RCSRemoteResourceObject::Ptr){ proceed_on_condition(); });
+
+ RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
+ uri, resourceTypes, resourceDiscoveredForTwoTimesCall);
+
+ waitForDiscoveryTask();
+}
+
+TEST_F(DiscoveryManagerTest, discoveryRequestByMultipleResourceTypesAndFindResourceOfOneResourceType)
+{
+ std::vector<std::string> resourceTypes{RESOURCETYPE, SECOND_RESOURCETYPE};
+ const std::string uri = "/oic/res";
+
+ createSecondResource();
+
+ mocks.ExpectCallFunc(resourceDiscoveredForCall).Do(
+ [this](RCSRemoteResourceObject::Ptr){ proceed();});
+
+ RCSDiscoveryManager::getInstance()->discoverResourceByTypes(RCSAddress::multicast(),
+ uri, resourceTypes, resourceDiscoveredForCall);
+
+ waitForDiscoveryTask();
+}
+
TEST_F(DiscoveryManagerTest, cancelDiscoveryTaskAfterDiscoveryResource)
{
startDiscovery();