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