1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "RCSDiscoveryManagerImpl.h"
23 #include "OCPlatform.h"
24 #include "PresenceSubscriber.h"
25 #include "RCSAddressDetail.h"
26 #include "RCSAddress.h"
27 #include "RCSRemoteResourceObject.h"
31 constexpr unsigned int POLLING_INTERVAL_TIME = 60000;
33 std::string makeResourceId(const std::shared_ptr< OIC::Service::PrimitiveResource >& resource)
35 return resource->getSid() + resource->getUri();
38 void validateTypes(const std::vector< std::string >& resourceTypes) {
39 if (resourceTypes.size() == 1) return;
41 for (const auto& type : resourceTypes)
43 if (type == OIC::Service::RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE)
45 throw OIC::Service::RCSBadRequestException{
46 "resource types must have no empty string!" };
56 constexpr RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::INVALID_ID;
57 constexpr char const* RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE;
59 RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
61 subscribePresenceWithMulticast();
63 m_timer.post(POLLING_INTERVAL_TIME,
64 std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
67 RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
69 static RCSDiscoveryManagerImpl instance;
73 void RCSDiscoveryManagerImpl::onResourceFound(
74 std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
75 const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
78 std::lock_guard < std::mutex > lock(m_mutex);
79 auto it = m_discoveryMap.find(discoveryId);
81 if (it == m_discoveryMap.end()) return;
82 if (it->second.isKnownResource(resource)) return;
84 it->second.addKnownResource(resource);
86 discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
89 RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
90 const RCSAddress& address, const std::string& relativeUri,
91 const std::vector< std::string >& resourceTypes,
92 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
96 throw RCSInvalidParameterException{ "Callback is empty" };
99 validateTypes(resourceTypes);
101 const ID discoveryId = createId();
103 DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceTypes,
104 std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
105 std::placeholders::_1, discoveryId, std::move(cb)));
107 discoveryInfo.discover();
110 std::lock_guard < std::mutex > lock(m_mutex);
111 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
114 return std::unique_ptr< RCSDiscoveryManager::DiscoveryTask >(
115 new RCSDiscoveryManager::DiscoveryTask(discoveryId));
118 void RCSDiscoveryManagerImpl::subscribePresenceWithMulticast()
120 using namespace std::placeholders;
122 constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
124 OCDoHandle presenceHandle;
125 subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
126 OCConnectivityType::CT_DEFAULT,
127 std::bind(&RCSDiscoveryManagerImpl::onPresence, this, _1, _2, _3));
130 void RCSDiscoveryManagerImpl::onPolling()
133 std::lock_guard < std::mutex > lock(m_mutex);
135 for (const auto& it : m_discoveryMap)
137 it.second.discover();
140 m_timer.post(POLLING_INTERVAL_TIME,
141 std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
144 void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
145 const std::string& address)
147 if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
149 std::lock_guard < std::mutex > lock(m_mutex);
150 for (const auto& it : m_discoveryMap)
152 if (it.second.isMatchedAddress(address))
154 it.second.discover();
159 RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId() const
161 static ID s_nextId = INVALID_ID + 1;
163 std::lock_guard < std::mutex > lock(m_mutex);
165 while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
170 assert(s_nextId != INVALID_ID && "Invalid ID!");
175 void RCSDiscoveryManagerImpl::cancel(ID id)
177 std::lock_guard < std::mutex > lock(m_mutex);
178 m_discoveryMap.erase(id);
181 DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
182 const std::string& relativeUri, const std::vector< std::string >& resourceTypes,
183 DiscoverCallback cb) :
184 m_address{ address },
185 m_relativeUri{ relativeUri },
186 m_resourceTypes{ resourceTypes },
187 m_knownResourceIds{ },
188 m_discoverCb{ std::move(cb) }
190 if (m_resourceTypes.empty())
192 m_resourceTypes.push_back(RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE);
196 void DiscoveryRequestInfo::discover() const
198 for (const auto& it : m_resourceTypes)
200 discoverResource(m_address, m_relativeUri + "?rt=" + it, m_discoverCb);
204 bool DiscoveryRequestInfo::isKnownResource(
205 const std::shared_ptr< PrimitiveResource >& resource) const
207 return m_knownResourceIds.find(makeResourceId(resource)) != m_knownResourceIds.end();
210 void DiscoveryRequestInfo::addKnownResource(
211 const std::shared_ptr< PrimitiveResource >& resource)
213 m_knownResourceIds.insert(makeResourceId(resource));
216 bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
218 return RCSAddressDetail::getDetail(m_address)->isMulticast()
219 || RCSAddressDetail::getDetail(m_address)->getAddress() == address;