Merge branch 'security-CKM' into 'master'
[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 <limits>
21
22 #include "RCSDiscoveryManagerImpl.h"
23
24 #include "OCPlatform.h"
25 #include "PresenceSubscriber.h"
26 #include "RCSAddressDetail.h"
27 #include "RCSAddress.h"
28
29 namespace
30 {
31     constexpr unsigned int LIMITNUMBER = std::numeric_limits<unsigned int>::max();;
32     constexpr unsigned int INTERVALTIME = 60000;
33 }
34
35 namespace OIC
36 {
37     namespace Service
38     {
39         RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl()
40         {
41             srand(time(NULL));
42             requestMulticastPresence();
43             m_timer.post(INTERVALTIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
44         }
45
46         RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
47         {
48             static RCSDiscoveryManagerImpl instance;
49             return &instance;
50         }
51
52         void RCSDiscoveryManagerImpl::onResourceFound(std::shared_ptr< PrimitiveResource > resource,
53                     RCSDiscoveryManagerImpl::ID discoveryId, const RCSDiscoveryManager::ResourceDiscoveredCallback& discoverCB)
54         {
55             {
56                 std::lock_guard<std::mutex> lock(m_mutex);
57                 auto it = m_discoveryMap.find(discoveryId);
58
59                 if(it == m_discoveryMap.end()) return;
60                 if(it->second.isKnownResource(resource)) return;
61             }
62             discoverCB(std::make_shared<RCSRemoteResourceObject>(resource));
63         }
64
65         RCSDiscoveryManager::DiscoveryTask::Ptr RCSDiscoveryManagerImpl::startDiscovery
66                 (const RCSAddress& address, const std::string& relativeUri, const std::string& resourceType,
67                         RCSDiscoveryManager::ResourceDiscoveredCallback cb)
68         {
69             if (!cb)
70             {
71                 throw RCSInvalidParameterException { "Callback is empty" };
72             }
73
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();
80
81             m_discoveryMap.insert(std::make_pair(discoveryId, std::move(discoveryItem)));
82
83             return std::unique_ptr<RCSDiscoveryManager::DiscoveryTask>(
84                     new RCSDiscoveryManager::DiscoveryTask(discoveryId));
85         }
86
87         void RCSDiscoveryManagerImpl::requestMulticastPresence()
88         {
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)));
94         }
95
96         void RCSDiscoveryManagerImpl::onPolling()
97         {
98             std::lock_guard<std::mutex> lock(m_mutex);
99
100             for(const auto& it : m_discoveryMap)
101             {
102                 it.second.discoverRequest();
103             }
104             m_timer.post(INTERVALTIME, std::bind(&RCSDiscoveryManagerImpl::onPolling, this));
105         }
106
107         void RCSDiscoveryManagerImpl::onPresence(OCStackResult ret,
108                 const unsigned int /*seq*/, const std::string& address)
109         {
110             if(ret != OC_STACK_OK && ret != OC_STACK_RESOURCE_CREATED) return;
111
112             std::lock_guard<std::mutex> lock(m_mutex);
113             for(const auto& it : m_discoveryMap)
114             {
115                 if(it.second.isMatchingAddress(address))
116                 {
117                     it.second.discoverRequest();
118                 }
119             }
120         }
121
122         RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
123         {
124             std::lock_guard<std::mutex> lock(m_mutex);
125             static unsigned int s_uniqueId;
126
127             if(m_discoveryMap.size() >= LIMITNUMBER)
128             {
129                 throw RCSException { "Discovery request is full!" };
130             }
131
132             while(m_discoveryMap.find(s_uniqueId) != m_discoveryMap.end())
133             {
134                 s_uniqueId++;
135             }
136             return s_uniqueId;
137         }
138
139         void RCSDiscoveryManagerImpl::cancel(unsigned int id)
140         {
141             std::lock_guard<std::mutex> lock(m_mutex);
142             m_discoveryMap.erase(id);
143         }
144
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) {}
148
149         void DiscoverRequestInfo::discoverRequest() const
150         {
151             OIC::Service::discoverResource(m_address, m_relativeUri + "?rt=" + m_resourceType,
152                     OCConnectivityType::CT_DEFAULT, m_discoverCB);
153         }
154
155         bool DiscoverRequestInfo::isKnownResource(const std::shared_ptr<PrimitiveResource>& resource)
156         {
157             std::string resourceId = resource->getSid() + resource->getUri();
158
159             auto it = std::find(m_receivedIds.begin(), m_receivedIds.end(), resourceId);
160
161             if(it != m_receivedIds.end()) return true;
162             m_receivedIds.push_back(resourceId);
163             return false;
164         }
165
166         bool DiscoverRequestInfo::isMatchingAddress(const std::string& address) const
167         {
168             return m_address == RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress()
169                     || m_address == address;
170         }
171     }
172 }