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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 #include "RCSDiscoveryManagerImpl.h"
24 #include "OCPlatform.h"
25 #include "PresenceSubscriber.h"
26 #include "RCSAddressDetail.h"
27 #include "RCSAddress.h"
31 constexpr unsigned int LIMITNUMBER = std::numeric_limits<unsigned int>::max();
32 constexpr unsigned int INTERVALTIME = 60000;
39 RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
42 requestMulticastPresence();
43 m_timer.post(INTERVALTIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
46 RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
48 static RCSDiscoveryManagerImpl instance;
52 void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr< PrimitiveResource > resource,
53 RCSDiscoveryManagerImpl::ID discoveryId,
54 const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
57 std::lock_guard<std::mutex> lock(m_mutex);
58 auto it = m_discoveryMap.find(discoveryId);
60 if(it == m_discoveryMap.end()) return;
61 if(it->second.isKnownResource(resource)) return;
63 discoverCB(std::make_shared<RCSRemoteResourceObject>(resource));
66 RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery
67 (const RCSAddress& address, const std::string& relativeUri, const std::string& resourceType,
68 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
72 throw RCSInvalidParameterException { "Callback is empty" };
75 ID discoveryId = createId();
76 auto discoverCb = std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
77 std::placeholders::_1, discoveryId, std::move(cb));
78 DiscoveryRequestInfo discoveryItem(RCSAddressDetail::getDetail(address)->getAddress(), relativeUri,
79 resourceType, std::move(discoverCb));
80 discoveryItem.discoverRequest();
82 std::lock_guard<std::mutex> lock(m_mutex);
83 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryItem)));
85 return std::unique_ptr<RCSDiscoveryManager::DiscoveryTask>(
86 new RCSDiscoveryManager::DiscoveryTask(discoveryId));
89 void RCSDiscoveryManagerImpl::requestMulticastPresence()
91 static constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
92 OCDoHandle presenceHandle;
93 subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS, OCConnectivityType::CT_DEFAULT,
94 std::move(std::bind(&RCSDiscoveryManagerImpl::onPresence, this,
95 std::placeholders::_1, std::placeholders::_2,std::placeholders::_3)));
98 void RCSDiscoveryManagerImpl::onPolling()
100 std::lock_guard<std::mutex> lock(m_mutex);
102 for(const auto& it : m_discoveryMap)
104 it.second.discoverRequest();
106 m_timer.post(INTERVALTIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
109 void RCSDiscoveryManagerImpl::onPresence(OCStackResult ret,
110 const unsigned int /*seq*/, const std::string& address)
112 if(ret != OC_STACK_OK && ret != OC_STACK_RESOURCE_CREATED) return;
114 std::lock_guard<std::mutex> lock(m_mutex);
115 for(const auto& it : m_discoveryMap)
117 if(it.second.isMatchingAddress(address))
119 it.second.discoverRequest();
124 RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
126 std::lock_guard<std::mutex> lock(m_mutex);
127 static unsigned int s_uniqueId;
129 if(m_discoveryMap.size() >= LIMITNUMBER)
131 throw RCSException { "Discovery request is full!" };
134 while(m_discoveryMap.find(s_uniqueId) != m_discoveryMap.end())
141 void RCSDiscoveryManagerImpl::cancel(unsigned int id)
143 std::lock_guard<std::mutex> lock(m_mutex);
144 m_discoveryMap.erase(id);
147 bool RCSDiscoveryManagerImpl::isCanceled(unsigned int id)
149 std::lock_guard<std::mutex> lock(m_mutex);
150 auto it = m_discoveryMap.find(id);
151 if(it == m_discoveryMap.end()) return true;
156 DiscoveryRequestInfo::DiscoveryRequestInfo(const std::string &address, const std::string &relativeUri,
157 const std::string &resourceType, DiscoverCallback cb) : m_address(address),
158 m_relativeUri(relativeUri), m_resourceType(resourceType), m_discoverCB(cb) {}
160 void DiscoveryRequestInfo::discoverRequest() const
162 OIC::Service::discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType,
163 OCConnectivityType::CT_DEFAULT, m_discoverCB);
166 bool DiscoveryRequestInfo::isKnownResource(const std::shared_ptr<PrimitiveResource>& resource)
168 std::string resourceId = resource->getSid() + resource->getUri();
170 auto it = std::find(m_receivedIds.begin(), m_receivedIds.end(), resourceId);
172 if(it != m_receivedIds.end()) return true;
173 m_receivedIds.push_back(resourceId);
177 bool DiscoveryRequestInfo::isMatchingAddress(const std::string& address) const
179 return m_address == RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress()
180 || m_address == address;