Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceBroker / src / ResourcePresence.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
21 #include "ResourcePresence.h"
22
23 #include <bits/atomic_base.h>
24 #include <bits/shared_ptr_base.h>
25 #include <time.h>
26 #include <unistd.h>
27 #include <cstdbool>
28 #include <exception>
29 #include <iostream>
30 #include <memory>
31
32 #include "PrimitiveResource.h"
33 #include "DeviceAssociation.h"
34 #include "DevicePresence.h"
35
36 namespace
37 {
38 using namespace OIC::Service;
39
40     void getCallback(const HeaderOptions &hos, const ResponseStatement& rep,
41             int eCode, std::weak_ptr<ResourcePresence> this_ptr)
42     {
43         OC_LOG_V(DEBUG,BROKER_TAG,"getCallback().\n");
44         std::shared_ptr<ResourcePresence> Ptr = this_ptr.lock();
45         if(Ptr)
46         {
47             Ptr->getCB(hos, rep, eCode);
48         }
49     }
50     void timeOutCallback(unsigned int msg, std::weak_ptr<ResourcePresence> this_ptr)
51     {
52         OC_LOG_V(DEBUG,BROKER_TAG,"timeOutCallback().\n");
53         std::shared_ptr<ResourcePresence> Ptr = this_ptr.lock();
54         if(Ptr)
55         {
56             Ptr->timeOutCB(msg);
57         }
58     }
59 }
60
61 namespace OIC
62 {
63     namespace Service
64     {
65         ResourcePresence::ResourcePresence()
66         : requesterList(nullptr), primitiveResource(nullptr),
67           state(BROKER_STATE::REQUESTED), mode(BROKER_MODE::NON_PRESENCE_MODE),
68           isWithinTime(true), receivedTime(0L), timeoutHandle(0)
69         {
70         }
71
72         void ResourcePresence::initializeResourcePresence(PrimitiveResourcePtr pResource)
73         {
74             OC_LOG_V(DEBUG,BROKER_TAG,"initializeResourcePresence().\n");
75             pGetCB = std::bind(getCallback, std::placeholders::_1, std::placeholders::_2,
76                     std::placeholders::_3, std::weak_ptr<ResourcePresence>(shared_from_this()));
77             pTimeoutCB = std::bind(timeOutCallback, std::placeholders::_1,
78                     std::weak_ptr<ResourcePresence>(shared_from_this()));
79             pPollingCB = std::bind(&ResourcePresence::pollingCB, this, std::placeholders::_1);
80
81             primitiveResource = pResource;
82             requesterList
83             = std::unique_ptr<std::list<BrokerRequesterInfoPtr>>
84             (new std::list<BrokerRequesterInfoPtr>);
85
86             timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND, pTimeoutCB);
87             OC_LOG_V(DEBUG,BROKER_TAG,"initializeResourcePresence::requestGet.\n");
88             primitiveResource->requestGet(pGetCB);
89
90             registerDevicePresence();
91         }
92
93
94         ResourcePresence::~ResourcePresence()
95         {
96             std::string deviceAddress = primitiveResource->getHost();
97
98             DevicePresencePtr foundDevice
99             = DeviceAssociation::getInstance()->findDevice(deviceAddress);
100
101             if(foundDevice != nullptr)
102             {
103                 foundDevice->removePresenceResource(this);
104
105                 if(foundDevice->isEmptyResourcePresence())
106                 {
107                     DeviceAssociation::getInstance()->removeDevice(foundDevice);
108                 }
109             }
110
111             requesterList->clear();
112
113             state = BROKER_STATE::DESTROYED;
114         }
115
116         void ResourcePresence::addBrokerRequester(BrokerID _id, BrokerCB _cb)
117         {
118             OC_LOG_V(DEBUG,BROKER_TAG,"addBrokerRequester().\n");
119             requesterList->push_back(
120                     std::make_shared<BrokerRequesterInfo>(BrokerRequesterInfo(_id, _cb)));
121         }
122
123         void ResourcePresence::removeAllBrokerRequester()
124         {
125             OC_LOG_V(DEBUG,BROKER_TAG,"removeAllBrokerRequester().\n");
126             if(requesterList != nullptr)
127             {
128                 requesterList->erase(requesterList->begin(), requesterList->end());
129             }
130         }
131
132         void ResourcePresence::removeBrokerRequester(BrokerID _id)
133         {
134             OC_LOG_V(DEBUG,BROKER_TAG,"removeBrokerRequester().\n");
135             std::list<BrokerRequesterInfoPtr>::iterator iter = requesterList->begin();
136             for(; iter != requesterList->end(); ++iter)
137             {
138                 if(iter->get()->brokerId == _id)
139                 {
140                     OC_LOG_V(DEBUG,BROKER_TAG,"find broker-id in requesterList.\n");
141                     requesterList->erase(iter);
142                     break;
143                 }
144             }
145         }
146
147         bool ResourcePresence::isEmptyRequester() const
148         {
149             OC_LOG_V(DEBUG,BROKER_TAG,"isEmptyRequester().\n");
150             return (requesterList!=nullptr)?requesterList->empty():true;
151         }
152
153         int ResourcePresence::requesterListSize() const {
154             OC_LOG_V(DEBUG,BROKER_TAG,"requesterListSize().\n");
155             return (requesterList!=nullptr)?requesterList->size():0;
156         }
157
158         void ResourcePresence::requestResourceState() const
159         {
160             OC_LOG_V(DEBUG,BROKER_TAG,"requestResourceState().\n");
161             primitiveResource->requestGet(pGetCB);
162             OC_LOG_V(DEBUG, BROKER_TAG, "Request Get\n");
163         }
164
165         void ResourcePresence::registerDevicePresence()
166         {
167             OC_LOG_V(DEBUG,BROKER_TAG,"registerDevicePresence().\n");
168             std::string deviceAddress = primitiveResource->getHost();
169
170             DevicePresencePtr foundDevice
171             = DeviceAssociation::getInstance()->findDevice(deviceAddress);
172
173             if(foundDevice == nullptr)
174             {
175                 try
176                 {
177                     foundDevice.reset(new DevicePresence());
178                     foundDevice->initializeDevicePresence(primitiveResource);
179                 }catch(...)
180                 {
181                     throw;
182                 }
183                 DeviceAssociation::getInstance()->addDevice(foundDevice);
184             }
185             foundDevice->addPresenceResource(this);
186         }
187
188         void ResourcePresence::executeAllBrokerCB(BROKER_STATE changedState)
189         {
190             OC_LOG_V(DEBUG, BROKER_TAG, "executeAllBrokerCB().\n");
191             if(state != changedState)
192             {
193                 setResourcestate(changedState);
194                 if(requesterList->empty() != true)
195                 {
196                     std::list<BrokerRequesterInfoPtr> list = * requesterList;
197                     for(BrokerRequesterInfoPtr item : list)
198                     {
199                         item->brokerCB(state);
200                     }
201                 }
202             }
203         }
204
205         void ResourcePresence::setResourcestate(BROKER_STATE _state)
206         {
207             OC_LOG_V(DEBUG, BROKER_TAG, "setResourcestate().\n");
208             this->state = _state;
209         }
210
211         void ResourcePresence::timeOutCB(unsigned int /*msg*/)
212         {
213             OC_LOG_V(DEBUG, BROKER_TAG, "timeOutCB()");
214             OC_LOG_V(DEBUG, BROKER_TAG, "waiting for terminate getCB\n");
215             std::unique_lock<std::mutex> lock(cbMutex);
216
217             time_t currentTime;
218             time(&currentTime);
219             currentTime += 0L;
220
221             if((receivedTime.load(boost::memory_order_consume) == 0) ||
222               ((receivedTime + BROKER_SAFE_SECOND) > currentTime ))
223             {
224                 this->isWithinTime = true;
225                 return;
226             }
227             this->isWithinTime = false;
228             OC_LOG_V(DEBUG, BROKER_TAG,
229                     "Timeout execution. will be discard after receiving cb message.\n");
230
231             executeAllBrokerCB(BROKER_STATE::LOST_SIGNAL);
232             pollingCB();
233         }
234
235         void ResourcePresence::pollingCB(unsigned int /*msg*/)
236         {
237             OC_LOG_V(DEBUG, BROKER_TAG, "pollingCB().\n");
238             if(this->requesterList->size() != 0)
239             {
240                 this->requestResourceState();
241                 timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
242             }
243         }
244
245         void ResourcePresence::getCB(const HeaderOptions & /*hos*/,
246                 const ResponseStatement & /*rep*/, int eCode)
247         {
248             OC_LOG_V(DEBUG, BROKER_TAG, "getCB().\n");
249             OC_LOG_V(DEBUG, BROKER_TAG, "waiting for terminate TimeoutCB.\n");
250             std::unique_lock<std::mutex> lock(cbMutex);
251
252             time_t currentTime;
253             time(&currentTime);
254             receivedTime = currentTime;
255
256             verifiedGetResponse(eCode);
257
258             if(isWithinTime)
259             {
260                 expiryTimer.cancel(timeoutHandle);
261                 isWithinTime = true;
262             }
263
264             if(mode == BROKER_MODE::NON_PRESENCE_MODE)
265             {
266                 expiryTimer.post(BROKER_SAFE_MILLISECOND,pPollingCB);
267             }
268
269         }
270
271         void ResourcePresence::verifiedGetResponse(int eCode)
272         {
273             OC_LOG_V(DEBUG, BROKER_TAG, "verifiedGetResponse().\n");
274             BROKER_STATE verifiedState = BROKER_STATE::NONE;
275             switch(eCode)
276             {
277             case OC_STACK_OK:
278             case OC_STACK_CONTINUE:
279                 verifiedState = BROKER_STATE::ALIVE;
280                 break;
281
282             case OC_STACK_RESOURCE_DELETED:
283                 verifiedState = BROKER_STATE::DESTROYED;
284                 break;
285
286             case OC_STACK_INVALID_REQUEST_HANDLE:
287             case OC_STACK_TIMEOUT:
288             case OC_STACK_COMM_ERROR:
289             case OC_STACK_PRESENCE_STOPPED:
290             case OC_STACK_PRESENCE_TIMEOUT:
291             default:
292                 verifiedState = BROKER_STATE::LOST_SIGNAL;
293                 break;
294             }
295
296             executeAllBrokerCB(verifiedState);
297             OC_LOG_V(DEBUG, BROKER_TAG, "resource state : %d",(int)state);
298         }
299
300         const PrimitiveResourcePtr ResourcePresence::getPrimitiveResource() const
301         {
302             OC_LOG_V(DEBUG, BROKER_TAG, "getPrimitiveResource()\n");
303             return primitiveResource;
304         }
305
306         BROKER_STATE ResourcePresence::getResourceState() const
307         {
308             OC_LOG_V(DEBUG, BROKER_TAG, "getResourceState()\n");
309             return state;
310         }
311
312         void ResourcePresence::changePresenceMode(BROKER_MODE newMode)
313         {
314             OC_LOG_V(DEBUG, BROKER_TAG, "changePresenceMode()\n");
315             if(newMode != mode)
316             {
317                 expiryTimer.cancel(timeoutHandle);
318                 if(newMode == BROKER_MODE::NON_PRESENCE_MODE)
319                 {
320                     timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
321                     requestResourceState();
322                 }
323                 mode = newMode;
324             }
325         }
326     } // namespace Service
327 } // namespace OIC