Merge branch 'master' into easysetup
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceClient / RCSDiscoveryManagerImpl.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20 #include "RCSDiscoveryManagerImpl.h"
21
22 #include "OCPlatform.h"
23 #include "PresenceSubscriber.h"
24 #include "RCSAddressDetail.h"
25 #include "RCSAddress.h"
26
27 namespace
28 {
29     constexpr unsigned int POLLING_INTERVAL_TIME = 60000;
30 }
31
32 namespace OIC
33 {
34     namespace Service
35     {
36         RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
37         {
38             srand (time(NULL));
39             requestMulticastPresence();
40             m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
41         }
42
43         RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
44         {
45             static RCSDiscoveryManagerImpl instance;
46             return &instance;
47         }
48
49         void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr<PrimitiveResource> resource,
50                 RCSDiscoveryManagerImpl::ID discoveryId,
51                 const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
52         {
53             {
54                 std::lock_guard < std::mutex > lock(m_mutex);
55                 auto it = m_discoveryMap.find(discoveryId);
56
57                 if (it == m_discoveryMap.end()) return;
58                 if (it->second.isKnownResource(resource)) return;
59             }
60             discoverCB(std::make_shared < RCSRemoteResourceObject > (resource));
61         }
62
63         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery(
64                 const RCSAddress& address, const std::string& relativeUri,
65                 const std::string& resourceType, RCSDiscoveryManager::ResourceDiscoveredCallback cb)
66         {
67             if (!cb)
68             {
69                 throw RCSInvalidParameterException { "Callback is empty" };
70             }
71
72             ID discoveryId = createId();
73             auto discoverCb = std::bind(&RCSDiscoveryManagerImpl::onResourceFound, this,
74                     std::placeholders::_1, discoveryId, std::move(cb));
75             DiscoveryRequestInfo discoveryInfo(RCSAddressDetail::getDetail(address)->getAddress(),
76                     relativeUri, resourceType, std::move(discoverCb));
77             discoveryInfo.discover();
78
79             {
80                 std::lock_guard < std::mutex > lock(m_mutex);
81                 m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryInfo)));
82             }
83
84             return std::unique_ptr < RCSDiscoveryManager::DiscoveryTask> (
85                     new RCSDiscoveryManager::DiscoveryTask(discoveryId));
86         }
87
88         void RCSDiscoveryManagerImpl::requestMulticastPresence()
89         {
90             constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
91             OCDoHandle presenceHandle;
92             subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
93                     OCConnectivityType::CT_DEFAULT,
94                     std::move(std::bind(&RCSDiscoveryManagerImpl::onPresence, this,
95                             std::placeholders::_1, std::placeholders::_2,
96                             std::placeholders::_3)));
97         }
98
99         void RCSDiscoveryManagerImpl::onPolling()
100         {
101             std::lock_guard < std::mutex > lock(m_mutex);
102
103             for (const auto& it : m_discoveryMap)
104             {
105                 it.second.discover();
106             }
107             m_timer.post(POLLING_INTERVAL_TIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
108         }
109
110         void RCSDiscoveryManagerImpl::onPresence(OCStackResult ret, const unsigned int /*seq*/,
111                 const std::string& address)
112         {
113             if (ret != OC_STACK_OK && ret != OC_STACK_RESOURCE_CREATED) return;
114
115             std::lock_guard < std::mutex > lock(m_mutex);
116             for (const auto& it : m_discoveryMap)
117             {
118                 if (it.second.isMatchingAddress(address))
119                 {
120                     it.second.discover();
121                 }
122             }
123         }
124
125         RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
126         {
127             std::lock_guard < std::mutex > lock(m_mutex);
128             static ID s_uniqueId;
129
130             s_uniqueId++;
131             while (m_discoveryMap.find(s_uniqueId) != m_discoveryMap.end())
132             {
133                 s_uniqueId++;
134             }
135             return s_uniqueId;
136         }
137
138         void RCSDiscoveryManagerImpl::cancel(ID id)
139         {
140             std::lock_guard < std::mutex > lock(m_mutex);
141             m_discoveryMap.erase(id);
142         }
143
144         bool RCSDiscoveryManagerImpl::isCanceled(ID id)
145         {
146             std::lock_guard < std::mutex > lock(m_mutex);
147             auto it = m_discoveryMap.find(id);
148             if (it == m_discoveryMap.end()) return true;
149
150             return false;
151         }
152
153         DiscoveryRequestInfo::DiscoveryRequestInfo(const std::string &address,
154                 const std::string &relativeUri, const std::string &resourceType,
155                 DiscoverCallback cb) :
156                 m_address(address), m_relativeUri(relativeUri), m_resourceType(resourceType),
157                 m_discoverCb(std::move(cb))
158         {
159         }
160
161         void DiscoveryRequestInfo::discover() const
162         {
163             OIC::Service::discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType,
164                     OCConnectivityType::CT_DEFAULT, m_discoverCb);
165         }
166
167         bool DiscoveryRequestInfo::isKnownResource(
168                 const std::shared_ptr<PrimitiveResource>& resource)
169         {
170             std::string resourceId = resource->getSid() + resource->getUri();
171
172             auto it = std::find(m_receivedIds.begin(), m_receivedIds.end(), resourceId);
173
174             if (it != m_receivedIds.end()) return true;
175             m_receivedIds.insert(resourceId);
176             return false;
177         }
178
179         bool DiscoveryRequestInfo::isMatchingAddress(const std::string& address) const
180         {
181             return m_address == RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress()
182                     || m_address == address;
183         }
184     }
185 }