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