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;
45 RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
47 subscribePresenceWithMuticast();
49 m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
52 RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
54 static RCSDiscoveryManagerImpl instance;
58 void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr<PrimitiveResource> resource,
59 ID discoveryId, const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
62 std::lock_guard< std::mutex > lock(m_mutex);
63 auto it = m_discoveryMap.find(discoveryId);
65 if (it == m_discoveryMap.end()) return;
66 if (it->second.isKnownResource(resource)) return;
68 it->second.addKnownResource(resource);
70 discoverCB(std::make_shared< RCSRemoteResourceObject > (resource));
73 RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
74 const RCSAddress& address, const std::string& relativeUri,
75 const std::string& resourceType, RCSDiscoveryManager::ResourceDiscoveredCallback cb)
79 throw RCSInvalidParameterException{ "Callback is empty" };
82 const ID discoveryId = createId();
84 DiscoveryRequestInfo discoveryInfo(address, relativeUri, resourceType,
85 std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
86 std::placeholders::_1, discoveryId, std::move(cb)));
87 discoveryInfo.discover();
90 std::lock_guard< std::mutex > lock(m_mutex);
91 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
94 return std::unique_ptr< RCSDiscoveryManager::DiscoveryTask >(
95 new RCSDiscoveryManager::DiscoveryTask(discoveryId));
98 void RCSDiscoveryManagerImpl::subscribePresenceWithMuticast()
100 using namespace std::placeholders;
102 constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
104 OCDoHandle presenceHandle;
105 subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
106 OCConnectivityType::CT_DEFAULT,
107 std::bind(&RCSDiscoveryManagerImpl::onPresence, this, _1, _2, _3));
110 void RCSDiscoveryManagerImpl::onPolling()
113 std::lock_guard< std::mutex > lock(m_mutex);
115 for (const auto& it : m_discoveryMap)
117 it.second.discover();
120 m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
123 void RCSDiscoveryManagerImpl::onPresence(OCStackResult result, const unsigned int /*seq*/,
124 const std::string& address)
126 if (result != OC_STACK_OK && result != OC_STACK_RESOURCE_CREATED) return;
128 std::lock_guard< std::mutex > lock(m_mutex);
129 for (const auto& it : m_discoveryMap)
131 if (it.second.isMatchedAddress(address))
133 it.second.discover();
138 RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId() const
140 static ID s_nextId = INVALID_ID + 1;
142 std::lock_guard< std::mutex > lock(m_mutex);
144 while (s_nextId == INVALID_ID || m_discoveryMap.find(s_nextId) != m_discoveryMap.end())
149 assert(s_nextId != INVALID_ID && "Invalid ID!");
154 void RCSDiscoveryManagerImpl::cancel(ID id)
156 std::lock_guard< std::mutex > lock(m_mutex);
157 m_discoveryMap.erase(id);
160 DiscoveryRequestInfo::DiscoveryRequestInfo(const RCSAddress& address,
161 const std::string& relativeUri, const std::string& resourceType,
162 DiscoverCallback cb) :
163 m_address{ address },
164 m_relativeUri{ relativeUri },
165 m_resourceType{ resourceType },
166 m_knownResourceIds{ },
167 m_discoverCb{ std::move(cb) }
171 void DiscoveryRequestInfo::discover() const
173 discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType, m_discoverCb);
176 bool DiscoveryRequestInfo::isKnownResource(
177 const std::shared_ptr< PrimitiveResource >& resource) const
179 return m_knownResourceIds.find(makeResourceId(resource)) != m_knownResourceIds.end();
182 void DiscoveryRequestInfo::addKnownResource(
183 const std::shared_ptr< PrimitiveResource >& resource)
185 m_knownResourceIds.insert(makeResourceId(resource));
188 bool DiscoveryRequestInfo::isMatchedAddress(const std::string& address) const
190 return RCSAddressDetail::getDetail(m_address)->isMulticast() ||
191 RCSAddressDetail::getDetail(m_address)->getAddress() == address;