3cb127efeb3cdb907aaa6f2dc6ddaea50e2429d9
[platform/upstream/iotivity.git] / service / notification-manager / NotificationManager / src / HostingObject.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 "HostingObject.h"
22
23 namespace OIC
24 {
25 namespace Service
26 {
27
28 void OIC_HOSTING_LOG(LogLevel level, const char * format, ...)
29 {
30     if (!format)
31     {
32         return;
33     }
34     char buffer[MAX_LOG_V_BUFFER_SIZE] = {};
35     va_list args;
36     va_start(args, format);
37     vsnprintf(buffer, sizeof buffer - 1, format, args);
38     va_end(args);
39     OCLog(level, PCF("Hosting"), buffer);
40 }
41
42 namespace
43 {
44     std::mutex mutexForCB;
45 }
46
47 HostingObject::HostingObject()
48 : remoteObject(nullptr), mirroredServer(nullptr),
49   remoteState(ResourceState::NONE),
50   pStateChangedCB(nullptr), pDataUpdateCB(nullptr),
51   pDestroyCB(nullptr), pSetRequestHandler(nullptr)
52 {
53 }
54
55 HostingObject::~HostingObject()
56 {
57         // shared_ptr release
58     pStateChangedCB = {};
59     pDataUpdateCB = {};
60
61     if (remoteObject)
62     {
63         remoteObject->stopMonitoring();
64         remoteObject->stopCaching();
65     }
66 }
67
68 HostingObject::RemoteObjectPtr HostingObject::getRemoteResource() const
69 {
70     return remoteObject;
71 }
72
73 void HostingObject::initializeHostingObject(RemoteObjectPtr rResource, DestroyedCallback destroyCB)
74 {
75     remoteObject = rResource;
76
77     pStateChangedCB = std::bind(&HostingObject::stateChangedCB, this,
78             std::placeholders::_1, remoteObject);
79     pDataUpdateCB = std::bind(&HostingObject::dataChangedCB, this,
80             std::placeholders::_1, remoteObject);
81     pDestroyCB = destroyCB;
82
83     pSetRequestHandler = std::bind(&HostingObject::setRequestHandler, this,
84             std::placeholders::_1, std::placeholders::_2);
85
86     try
87     {
88         remoteObject->startMonitoring(pStateChangedCB);
89         remoteObject->startCaching(pDataUpdateCB);
90     }catch(...)
91     {
92         throw;
93     }
94 }
95
96 void HostingObject::destroyHostingObject()
97 {
98     pDestroyCB();
99 }
100
101 void HostingObject::stateChangedCB(ResourceState state, RemoteObjectPtr rObject)
102 {
103     remoteState = state;
104
105     switch (state)
106     {
107     case ResourceState::ALIVE:
108     {
109         if(rObject->isCaching() == false)
110         {
111             try
112             {
113                 rObject->startCaching(pDataUpdateCB);
114             }catch(InvalidParameterException &e)
115             {
116                 OIC_HOSTING_LOG(DEBUG,
117                         "[HostingObject::stateChangedCB]startCaching InvalidParameterException:%s",
118                         e.what());
119             }
120         }
121         break;
122     }
123     case ResourceState::LOST_SIGNAL:
124     case ResourceState::DESTROYED:
125     {
126         if(rObject->isCaching() == true)
127         {
128             try
129             {
130                 rObject->stopCaching();
131             }catch(InvalidParameterException &e)
132             {
133                 OIC_HOSTING_LOG(DEBUG,
134                         "[HostingObject::stateChangedCB]stopCaching InvalidParameterException:%s",
135                         e.what());
136             }
137         }
138         if(rObject->isMonitoring() == true)
139         {
140             try
141             {
142                 rObject->stopMonitoring();
143             }catch(InvalidParameterException &e)
144             {
145                 OIC_HOSTING_LOG(DEBUG,
146                         "[HostingObject::stateChangedCB]stopWatching InvalidParameterException:%s",
147                         e.what());
148             }
149         }
150         mirroredServer = nullptr;
151         destroyHostingObject();
152         break;
153     }
154     default:
155         // not support of state
156         break;
157     }
158 }
159
160 void HostingObject::dataChangedCB(const RCSResourceAttributes & attributes, RemoteObjectPtr rObject)
161 {
162     std::unique_lock<std::mutex> lock(mutexForCB);
163     if(attributes.empty())
164     {
165         return;
166     }
167
168     if(mirroredServer == nullptr)
169     {
170         try
171         {
172             mirroredServer = createMirroredServer(rObject);
173         }catch(PlatformException &e)
174         {
175             OIC_HOSTING_LOG(DEBUG,
176                         "[HostingObject::dataChangedCB]createMirroredServer PlatformException:%s",
177                         e.what());
178             mirroredServer = nullptr;
179             return;
180         }
181     }
182
183     RCSResourceAttributes rData;
184     {
185         RCSResourceObject::LockGuard guard(mirroredServer);
186         rData = mirroredServer->getAttributes();
187     }
188     if(rData.empty() || rData != attributes)
189     {
190         {
191             RCSResourceObject::LockGuard guard(mirroredServer);
192             for(auto it = rData.begin(); ; ++it)
193             {
194                 if(it == rData.end())
195                 {
196                     break;
197                 }
198                 mirroredServer->removeAttribute(it->key());
199             }
200
201             for(auto it = attributes.begin();; ++it)
202             {
203                 if(it == attributes.end())
204                 {
205                     break;
206                 }
207                 mirroredServer->setAttribute(it->key(), it->value());
208             }
209         }
210     }
211 }
212
213 HostingObject::ResourceObjectPtr HostingObject::createMirroredServer(RemoteObjectPtr rObject)
214 {
215     ResourceObjectPtr retResource = nullptr;
216     if(rObject != nullptr)
217     {
218         std::string fulluri = rObject->getUri();
219         std::string uri = fulluri.substr(0, fulluri.size()-8);
220         std::vector<std::string> types = rObject->getTypes();
221         std::vector<std::string> interfaces = rObject->getInterfaces();
222         try
223         {
224             std::string type = types.begin()->c_str();
225             std::string interface = interfaces.begin()->c_str();
226             retResource = RCSResourceObject::Builder(uri, type, interface).
227                     setDiscoverable(true).setObservable(true).build();
228
229             // TODO need to bind types and interfaces
230             retResource->setAutoNotifyPolicy(RCSResourceObject::AutoNotifyPolicy::UPDATED);
231             retResource->setSetRequestHandler(pSetRequestHandler);
232         }catch(...)
233         {
234             OIC_HOSTING_LOG(DEBUG, "[HostingObject::createMirroredServer] %s", "PlatformException");
235             throw;
236         }
237     }
238     else
239     {
240         throw PlatformException(OC_STACK_ERROR);
241     }
242
243     return retResource;
244 }
245
246 RCSSetResponse HostingObject::setRequestHandler(const RCSRequest & primitiveRequest,
247             RCSResourceAttributes & resourceAttibutes)
248 {
249     (void)primitiveRequest;
250     try
251     {
252         RequestObject newRequest = { };
253         newRequest.invokeRequest(remoteObject, RequestObject::RequestMethod::Setter,
254                 resourceAttibutes);
255     }catch(PlatformException &e)
256     {
257         OIC_HOSTING_LOG(DEBUG,
258                 "[HostingObject::setRequestHandler] PlatformException:%s",
259                 e.what());
260         throw;
261     }
262
263     return RCSSetResponse::create(resourceAttibutes);
264 }
265
266 } /* namespace Service */
267 } /* namespace OIC */