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, const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
56 std::lock_guard<std::mutex> lock(m_mutex);
57 auto it = m_discoveryMap.find(discoveryId);
59 if(it == m_discoveryMap.end()) return;
60 if(it->second.isKnownResource(resource)) return;
62 discoverCB(std::make_shared<RCSRemoteResourceObject>(resource));
65 RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery
66 (const RCSAddress& address, const std::string& relativeUri, const std::string& resourceType,
67 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
71 throw RCSInvalidParameterException { "Callback is empty" };
74 ID discoveryId = createId();
75 auto discoverCb = std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
76 std::placeholders::_1, discoveryId, std::move(cb));
77 DiscoverRequestInfo discoveryItem(RCSAddressDetail::getDetail(address)->getAddress(), relativeUri,
78 resourceType, std::move(discoverCb));
79 discoveryItem.discoverRequest();
81 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryItem)));
83 return std::unique_ptr<RCSDiscoveryManager::DiscoveryTask>(
84 new RCSDiscoveryManager::DiscoveryTask(discoveryId));
87 void RCSDiscoveryManagerImpl::requestMulticastPresence()
89 static constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
90 OCDoHandle presenceHandle;
91 subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS, OCConnectivityType::CT_DEFAULT,
92 std::move(std::bind(&RCSDiscoveryManagerImpl::onPresence, this,
93 std::placeholders::_1, std::placeholders::_2,std::placeholders::_3)));
96 void RCSDiscoveryManagerImpl::onPolling()
98 std::lock_guard<std::mutex> lock(m_mutex);
100 for(const auto& it : m_discoveryMap)
102 it.second.discoverRequest();
104 m_timer.post(INTERVALTIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
107 void RCSDiscoveryManagerImpl::onPresence(OCStackResult ret,
108 const unsigned int /*seq*/, const std::string& address)
110 if(ret != OC_STACK_OK && ret != OC_STACK_RESOURCE_CREATED) return;
112 std::lock_guard<std::mutex> lock(m_mutex);
113 for(const auto& it : m_discoveryMap)
115 if(it.second.isMatchingAddress(address))
117 it.second.discoverRequest();
122 RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
124 std::lock_guard<std::mutex> lock(m_mutex);
125 static unsigned int s_uniqueId;
127 if(m_discoveryMap.size() >= LIMITNUMBER)
129 throw RCSException { "Discovery request is full!" };
132 while(m_discoveryMap.find(s_uniqueId) != m_discoveryMap.end())
139 void RCSDiscoveryManagerImpl::cancel(unsigned int id)
141 std::lock_guard<std::mutex> lock(m_mutex);
142 m_discoveryMap.erase(id);
145 DiscoverRequestInfo::DiscoverRequestInfo(const std::string &address, const std::string &relativeUri,
146 const std::string &resourceType, DiscoverCallback cb) : m_address(address),
147 m_relativeUri(relativeUri), m_resourceType(resourceType), m_discoverCB(cb) {}
149 void DiscoverRequestInfo::discoverRequest() const
151 OIC::Service::discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType,
152 OCConnectivityType::CT_DEFAULT, m_discoverCB);
155 bool DiscoverRequestInfo::isKnownResource(const std::shared_ptr<PrimitiveResource>& resource)
157 std::string resourceId = resource->getSid() + resource->getUri();
159 auto it = std::find(m_receivedIds.begin(), m_receivedIds.end(), resourceId);
161 if(it != m_receivedIds.end()) return true;
162 m_receivedIds.push_back(resourceId);
166 bool DiscoverRequestInfo::isMatchingAddress(const std::string& address) const
168 return m_address == RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress()
169 || m_address == address;