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();
43 constexpr RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::INVALID_ID;
44 constexpr char const* RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE;
46 RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
48 subscribePresenceWithMuticast();
50 m_timer.post(POLLING_INTERVAL_TIME,
51 std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
54 RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
56 static RCSDiscoveryManagerImpl instance;
60 void RCSDiscoveryManagerImpl::onResourceFound(
61 std::shared_ptr< PrimitiveResource > resource, ID discoveryId,
62 const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
65 std::lock_guard < std::mutex > lock(m_mutex);
66 auto it = m_discoveryMap.find(discoveryId);
68 if (it == m_discoveryMap.end()) return;
69 if (it->second.isKnownResource(resource)) return;
71 it->second.addKnownResource(resource);
73 discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
76 RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
77 const RCSAddress& address, const std::string& relativeUri,
78 const std::vector< std::string >& resourceTypes,
79 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
83 throw RCSInvalidParameterException{ "Callback is empty" };
86 for(auto it = resourceTypes.begin()+1; it < resourceTypes.end(); it++)
88 if ((*it).compare(ALL_RESOURCE_TYPE) == 0)
90 throw RCSInvalidParameterException{ "ResourceType is duplicated!" };
94 const ID discoveryId = createId();
96 DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceTypes,
97 std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
98 std::placeholders::_1, discoveryId, std::move(cb)));
100 discoveryInfo.discover();
103 std::lock_guard < std::mutex > lock(m_mutex);
104 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
107 return std::unique_ptr < RCSDiscoveryManager::DiscoveryTask
108 > (new RCSDiscoveryManager::DiscoveryTask(discoveryId));
111 void RCSDiscoveryManagerImpl::subscribePresenceWithMuticast()
113 using namespace std::placeholders;
115 constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
117 OCDoHandle presenceHandle;
118 subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
119 OCConnectivityType::CT_DEFAULT,
120 std::bind(&RCSDiscoveryManagerImpl::onPresence, this, _1, _2, _3));
123 void RCSDiscoveryManagerImpl::onPolling()
126 std::lock_guard < std::mutex > lock(m_mutex);
128 for (const auto& it : m_discoveryMap)
130 it.second.discover();
133 m_timer.post(POLLING_INTERVAL_TIME,
134 std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
137 void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
138 const std::string& address)
140 if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
142 std::lock_guard < std::mutex > lock(m_mutex);
143 for (const auto& it : m_discoveryMap)
145 if (it.second.isMatchedAddress(address))
147 it.second.discover();
152 RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId() const
154 static ID s_nextId = INVALID_ID + 1;
156 std::lock_guard < std::mutex > lock(m_mutex);
158 while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
163 assert(s_nextId != INVALID_ID && "Invalid ID!");
168 void RCSDiscoveryManagerImpl::cancel(ID id)
170 std::lock_guard < std::mutex > lock(m_mutex);
171 m_discoveryMap.erase(id);
174 DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
175 const std::string& relativeUri, const std::vector< std::string >& resourceTypes,
176 DiscoverCallback cb) :
177 m_address{ address },
178 m_relativeUri{ relativeUri },
179 m_resourceTypes{ resourceTypes },
180 m_knownResourceIds{ },
181 m_discoverCb{ std::move(cb) }
183 if (m_resourceTypes.empty())
185 m_resourceTypes.push_back(RCSDiscoveryManagerImpl::ALL_RESOURCE_TYPE);
189 void DiscoveryRequestInfo::discover() const
191 for (const auto& it : m_resourceTypes)
193 discoverResource(m_address, m_relativeUri + "?rt=" + it, m_discoverCb);
197 bool DiscoveryRequestInfo::isKnownResource(
198 const std::shared_ptr< PrimitiveResource >& resource) const
200 return m_knownResourceIds.find(makeResourceId(resource)) != m_knownResourceIds.end();
203 void DiscoveryRequestInfo::addKnownResource(
204 const std::shared_ptr< PrimitiveResource >& resource)
206 m_knownResourceIds.insert(makeResourceId(resource));
209 bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
211 return RCSAddressDetail::getDetail(m_address)->isMulticast()
212 || RCSAddressDetail::getDetail(m_address)->getAddress() == address;