Modify initialization for non-static class member.
[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::unique_lock<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(const RCSAddress& address,
79                 const std::string& relativeURI, const std::string& resourceType,
80                 RCSDiscoveryManager::ResourceDiscoveredCallback cb)
81         {
82             if (!cb)
83             {
84                 throw InvalidParameterException { "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>(new RCSDiscoveryManager::DiscoveryTask(discoverID));
104         }
105
106         void RCSDiscoveryManagerImpl::initializedDiscoveryEnvironment()
107         {
108             m_presenceCB = std::bind(&RCSDiscoveryManagerImpl::presenceCallback, this,
109                     std::placeholders::_1, std::placeholders::_2,std::placeholders::_3);
110             m_pollingCB = std::bind(&RCSDiscoveryManagerImpl::pollingCallback, this,
111                 std::placeholders::_1);
112         }
113
114         void RCSDiscoveryManagerImpl::requestMulticastPresence()
115         {
116             static constexpr char MULTICAST_PRESENCE_ADDRESS[] = "coap://" OC_MULTICAST_PREFIX;
117             OCDoHandle presenceHandle;
118             subscribePresence(presenceHandle, MULTICAST_PRESENCE_ADDRESS,
119                             OCConnectivityType::CT_DEFAULT, std::move(m_presenceCB));
120         }
121
122         bool RCSDiscoveryManagerImpl::isDuplicatedCallback(std::shared_ptr< PrimitiveResource > resource,
123                 ID discoverID)
124         {
125             std::string retID = resource->getSid()+resource->getUri();
126             auto it = m_discoveryMap.find(discoverID);
127             std::list<std::string>::iterator itor;
128             if(it==m_discoveryMap.end())
129             {
130                 return false;
131             }
132             itor = std::find(it->second.m_receivedIds.begin(),it->second.m_receivedIds.end(),retID);
133             if(itor != it->second.m_receivedIds.end())
134             {
135               return true;
136             }
137             it->second.m_receivedIds.push_back(retID);
138
139             return false;
140         }
141
142         void RCSDiscoveryManagerImpl::pollingCallback(unsigned int /*msg*/)
143         {
144             std::unique_lock<std::mutex> lock(m_mutex);
145             for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
146             {
147                 OIC::Service::discoverResource(it->second.m_address,it->second.m_relativeUri+ "?rt="
148                         +it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
149             }
150             m_timerHandle = m_timer.post(INTERVALTIME, m_pollingCB);
151         }
152
153         void RCSDiscoveryManagerImpl::presenceCallback(OCStackResult ret,
154                 const unsigned int /*seq*/, const std::string& /*address*/)
155         {
156             if(ret == OC_STACK_OK || ret == OC_STACK_RESOURCE_CREATED || ret == OC_STACK_RESOURCE_DELETED)
157             {
158                 std::unique_lock<std::mutex> lock(m_mutex);
159                 for(auto it = m_discoveryMap.begin(); it != m_discoveryMap.end(); ++it)
160                 {
161                     if(!it->second.m_isReceivedFindCallback)
162                     {
163                         OIC::Service::discoverResource(it->second.m_address, it->second.m_relativeUri+ "?rt=" +
164                             it->second.m_resourceType, OCConnectivityType::CT_DEFAULT, it->second.m_findCB);
165                     }
166                 }
167             }
168         }
169
170         RCSDiscoveryManagerImpl::ID RCSDiscoveryManagerImpl::createId()
171         {
172             std::unique_lock<std::mutex> lock(m_mutex);
173             if(s_uniqueId<LIMITNUMBER)
174             {
175                  s_uniqueId++;
176             }
177             else
178             {
179                 s_uniqueId = RESETNUMBER;
180             }
181             while(m_discoveryMap.size() != LIMITNUMBER)
182             {
183                 if(m_discoveryMap.find(s_uniqueId) == m_discoveryMap.end())
184                 {
185                     return s_uniqueId;
186                 }
187                 s_uniqueId++;
188             }
189
190             return RESETNUMBER;
191         }
192     }
193 }