Merge master to cloud-interface branch
[contrib/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 == 0) || ((receivedTime + BROKER_SAFE_SECOND) > currentTime ))
222             {
223                 this->isWithinTime = true;
224                 return;
225             }
226             this->isWithinTime = false;
227             OC_LOG_V(DEBUG, BROKER_TAG,
228                     "Timeout execution. will be discard after receiving cb message.\n");
229
230             executeAllBrokerCB(BROKER_STATE::LOST_SIGNAL);
231             pollingCB();
232         }
233
234         void ResourcePresence::pollingCB(unsigned int /*msg*/)
235         {
236             OC_LOG_V(DEBUG, BROKER_TAG, "pollingCB().\n");
237             if(this->requesterList->size() != 0)
238             {
239                 this->requestResourceState();
240                 timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
241             }
242         }
243
244         void ResourcePresence::getCB(const HeaderOptions & /*hos*/,
245                 const ResponseStatement & /*rep*/, int eCode)
246         {
247             OC_LOG_V(DEBUG, BROKER_TAG, "getCB().\n");
248             OC_LOG_V(DEBUG, BROKER_TAG, "waiting for terminate TimeoutCB.\n");
249             std::unique_lock<std::mutex> lock(cbMutex);
250
251             time_t currentTime;
252             time(&currentTime);
253             receivedTime = currentTime;
254
255             verifiedGetResponse(eCode);
256
257             if(isWithinTime)
258             {
259                 expiryTimer.cancel(timeoutHandle);
260                 isWithinTime = true;
261             }
262
263             if(mode == BROKER_MODE::NON_PRESENCE_MODE)
264             {
265                 expiryTimer.post(BROKER_SAFE_MILLISECOND,pPollingCB);
266             }
267
268         }
269
270         void ResourcePresence::verifiedGetResponse(int eCode)
271         {
272             OC_LOG_V(DEBUG, BROKER_TAG, "verifiedGetResponse().\n");
273             BROKER_STATE verifiedState = BROKER_STATE::NONE;
274             switch(eCode)
275             {
276             case OC_STACK_OK:
277             case OC_STACK_CONTINUE:
278                 verifiedState = BROKER_STATE::ALIVE;
279                 break;
280
281             case OC_STACK_RESOURCE_DELETED:
282                 verifiedState = BROKER_STATE::DESTROYED;
283                 break;
284
285             case OC_STACK_INVALID_REQUEST_HANDLE:
286             case OC_STACK_TIMEOUT:
287             case OC_STACK_COMM_ERROR:
288             case OC_STACK_PRESENCE_STOPPED:
289             case OC_STACK_PRESENCE_TIMEOUT:
290             default:
291                 verifiedState = BROKER_STATE::LOST_SIGNAL;
292                 break;
293             }
294
295             executeAllBrokerCB(verifiedState);
296             OC_LOG_V(DEBUG, BROKER_TAG, "resource state : %d",(int)state);
297         }
298
299         const PrimitiveResourcePtr ResourcePresence::getPrimitiveResource() const
300         {
301             OC_LOG_V(DEBUG, BROKER_TAG, "getPrimitiveResource()\n");
302             return primitiveResource;
303         }
304
305         BROKER_STATE ResourcePresence::getResourceState() const
306         {
307             OC_LOG_V(DEBUG, BROKER_TAG, "getResourceState()\n");
308             return state;
309         }
310
311         void ResourcePresence::changePresenceMode(BROKER_MODE newMode)
312         {
313             OC_LOG_V(DEBUG, BROKER_TAG, "changePresenceMode()\n");
314             if(newMode != mode)
315             {
316                 expiryTimer.cancel(timeoutHandle);
317                 if(newMode == BROKER_MODE::NON_PRESENCE_MODE)
318                 {
319                     timeoutHandle = expiryTimer.post(BROKER_SAFE_MILLISECOND,pTimeoutCB);
320                     requestResourceState();
321                 }
322                 mode = newMode;
323             }
324         }
325     } // namespace Service
326 } // namespace OIC