Merge branch 'master' into plugin-interface
[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
24 #include "PresenceSubscriber.h"
25 #include "RCSAddressDetail.h"
26 #include "RCSAddress.h"
27
28 constexpr unsigned int RESETNUMBER = 0;
29 constexpr unsigned int LIMITNUMBER = 1000;
30 constexpr unsigned int INTERVALTIME = 60000;
31
32 namespace OIC
33 {
34     namespace Service
35     {
36         unsigned int RCSDiscoveryManagerImpl::s_uniqueId = RESETNUMBER;
37         RCSDiscoveryManagerImpl * RCSDiscoveryManagerImpl::s_instance(nullptr);
38         std::mutex RCSDiscoveryManagerImpl::s_mutexForCreation;
39
40         RCSDiscoveryManagerImpl::RCSDiscoveryManagerImpl() : m_timerHandle(0){}
41
42         RCSDiscoveryManagerImpl* RCSDiscoveryManagerImpl::getInstance()
43         {
44             if (!s_instance)
45             {
46                 s_mutexForCreation.lock();
47                 if (!s_instance)
48                 {
49                     s_instance = new RCSDiscoveryManagerImpl();
50                     srand(time(NULL));
51                     s_instance->initializedDiscoveryEnvironment();
52                     s_instance->requestMulticastPresence();
53                     s_instance->m_timerHandle = s_instance->m_timer.post(INTERVALTIME, s_instance->m_pollingCB);
54                 }
55                 s_mutexForCreation.unlock();
56             }
57             return s_instance;
58         }
59
60         void RCSDiscoveryManagerImpl::findCallback(std::shared_ptr< PrimitiveResource > resource,
61             RCSDiscoveryManagerImpl::ID discoverID)
62         {
63             std::lock_guard<std::mutex> lock(m_mutex);
64
65            if(!isDuplicatedCallback(resource,discoverID))
66             {
67                for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
68                {
69                    if(it->first == discoverID)
70                    {
71                         it->second.m_isReceivedFindCallback = true;
72                         it->second.m_discoverCB(std::make_shared<RCSRemoteResourceObject>(resource));
73                    }
74                 }
75             }
76         }
77
78         std::unique_ptr<RCSDiscoveryManager::DiscoveryTask> RCSDiscoveryManagerImpl::startDiscovery
79         (const RCSAddress& address, const std::string& relativeURI, const std::string& resourceType,
80                 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
81         {
82             if (!cb)
83             {
84                 throw RCSInvalidParameterException { "input Parameter(callback) is NULL" };
85             }
86
87             DiscoverRequestInfo discoveryItem;
88             discoveryItem.m_address = RCSAddressDetail::getDetail(address)->getAddress();
89             discoveryItem.m_relativeUri = relativeURI;
90             discoveryItem.m_resourceType = resourceType;
91             discoveryItem.m_discoverCB = std::move(cb);
92             discoveryItem.m_isReceivedFindCallback = false;
93
94             ID discoverID = createId();
95             discoveryItem.m_findCB = std::bind(&RCSDiscoveryManagerImpl::findCallback, this,
96                     std::placeholders::_1, discoverID);
97             m_discoveryMap.insert(std::make_pair(discoverID, discoveryItem));
98
99             OIC::Service::discoverResource(RCSAddressDetail::getDetail(RCSAddress::multicast())->getAddress(),
100                     discoveryItem.m_relativeUri + "?rt=" +discoveryItem.m_resourceType,
101                     OCConnectivityType::CT_DEFAULT, discoveryItem.m_findCB);
102
103             return std::unique_ptr<RCSDiscoveryManager::DiscoveryTask>(
104                     new RCSDiscoveryManager::DiscoveryTask(discoverID));
105         }
106
107         void RCSDiscoveryManagerImpl::initializedDiscoveryEnvironment()
108         {
109             m_presenceCB = std::bind(&RCSDiscoveryManagerImpl::presenceCallback, this,
110                     std::placeholders::_1, std::placeholders::_2,std::placeholders::_3);
111             m_pollingCB = std::bind(&RCSDiscoveryManagerImpl::pollingCallback, this,
112                 std::placeholders::_1);
113         }
114
115         void RCSDiscoveryManagerImpl::requestMulticastPresence()
116         {
117             static constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
118             OCDoHandle presenceHandle;
119             subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
120                             OCConnectivityType::CT_DEFAULT, std::move(m_presenceCB));
121         }
122
123         bool RCSDiscoveryManagerImpl::isDuplicatedCallback(std::shared_ptr< PrimitiveResource > resource,
124                 ID discoverID)
125         {
126             std::string retID = resource->getSid()+resource->getUri();
127             auto it = m_discoveryMap.find(discoverID);
128             std::list<std::string>::iterator itor;
129             if(it==m_discoveryMap.end())
130             {
131                 return false;
132             }
133             itor = std::find(it->second.m_receivedIds.begin(),it->second.m_receivedIds.end(),retID);
134             if(itor != it->second.m_receivedIds.end())
135             {
136               return true;
137             }
138             it->second.m_receivedIds.push_back(retID);
139
140             return false;
141         }
142
143         void RCSDiscoveryManagerImpl::pollingCallback(unsigned int /*msg*/)
144         {
145             std::lock_guard<std::mutex> lock(m_mutex);
146             for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
147             {
148                 OIC::Service::discoverResource(it->second.m_address,it->second.m_relativeUri+ "?rt="
149                         +it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
150             }
151             m_timerHandle = m_timer.post(INTERVALTIME, m_pollingCB);
152         }
153
154         void RCSDiscoveryManagerImpl::presenceCallback(OCStackResult ret,
155                 const unsigned int /*seq*/, const std::string& /*address*/)
156         {
157             if(ret == OC_STACK_OK || ret == OC_STACK_RESOURCE_CREATED || ret == OC_STACK_RESOURCE_DELETED)
158             {
159                 std::lock_guard<std::mutex> lock(m_mutex);
160                 for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
161                 {
162                     if(!it->second.m_isReceivedFindCallback)
163                     {
164                         OIC::Service::discoverResource(it->second.m_address, it->second.m_relativeUri+ "?rt=" +
165                             it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
166                     }
167                 }
168             }
169         }
170
171         RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
172         {
173             std::lock_guard<std::mutex> lock(m_mutex);
174             if(s_uniqueId<LIMITNUMBER)
175             {
176                  s_uniqueId++;
177             }
178             else
179             {
180                 s_uniqueId = RESETNUMBER;
181             }
182             while(m_discoveryMap.size() != LIMITNUMBER)
183             {
184                 if(m_discoveryMap.find(s_uniqueId) == m_discoveryMap.end())
185                 {
186                     return s_uniqueId;
187                 }
188                 s_uniqueId++;
189             }
190
191             return RESETNUMBER;
192         }
193
194         void RCSDiscoveryManagerImpl::cancel(ID id)
195         {
196             std::lock_guard<std::mutex> lock(m_mutex);
197             m_discoveryMap.erase(id);
198         }
199     }
200 }