16d6a6570e1065003d466bba3a84a1acd0826d8f
[platform/upstream/iotivity.git] / service / simulator / src / server / simulator_single_resource_impl.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 "simulator_single_resource_impl.h"
22 #include "simulator_utils.h"
23 #include "simulator_logger.h"
24 #include "logger.h"
25
26 #define TAG "SIM_SINGLE_RESOURCE"
27
28 SimulatorSingleResourceImpl::SimulatorSingleResourceImpl()
29     :   m_type(SimulatorResource::Type::SINGLE_RESOURCE),
30         m_interfaces {OC::DEFAULT_INTERFACE},
31         m_resourceHandle(NULL)
32 {
33     m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
34 }
35
36 std::string SimulatorSingleResourceImpl::getName() const
37 {
38     return m_name;
39 }
40
41 SimulatorResource::Type SimulatorSingleResourceImpl::getType() const
42 {
43     return m_type;
44 }
45
46 std::string SimulatorSingleResourceImpl::getURI() const
47 {
48     return m_uri;
49 }
50
51 std::string SimulatorSingleResourceImpl::getResourceType() const
52 {
53     return m_resourceType;
54 }
55
56 std::vector<std::string> SimulatorSingleResourceImpl::getInterface() const
57 {
58     return m_interfaces;
59 }
60
61 void SimulatorSingleResourceImpl::setInterface(const std::vector<std::string> &interfaces)
62 {
63     m_interfaces = interfaces;
64 }
65
66 void SimulatorSingleResourceImpl::setName(const std::string &name)
67 {
68     VALIDATE_INPUT(name.empty(), "Name is empty!")
69
70     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
71     if (m_resourceHandle)
72     {
73         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
74                                  "Name can not be set when resource is started!");
75     }
76
77     m_name = name;
78 }
79
80 void SimulatorSingleResourceImpl::setURI(const std::string &uri)
81 {
82     VALIDATE_INPUT(uri.empty(), "Uri is empty!")
83
84     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
85     if (m_resourceHandle)
86     {
87         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
88                                  "URI can not be set when resource is started!");
89     }
90
91     m_uri = uri;
92 }
93
94 void SimulatorSingleResourceImpl::setResourceType(const std::string &resourceType)
95 {
96     VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
97
98     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
99     if (m_resourceHandle)
100     {
101         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
102                                  "Resource type can not be set when resource is started!");
103     }
104
105     m_resourceType = resourceType;
106 }
107
108 void SimulatorSingleResourceImpl::addInterface(std::string interfaceType)
109 {
110     VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
111
112     if (interfaceType == OC::LINK_INTERFACE
113         || interfaceType == OC::BATCH_INTERFACE
114         || interfaceType == OC::GROUP_INTERFACE)
115     {
116         throw NoSupportException("Single type resource does not support this interface!");
117     }
118
119     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
120     if (m_resourceHandle)
121     {
122         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
123                                  "Interface type can not be set when resource is started!");
124     }
125
126     auto found = std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType);
127     if (found != m_interfaces.end())
128         m_interfaces.push_back(interfaceType);
129 }
130
131 void SimulatorSingleResourceImpl::setObservable(bool state)
132 {
133     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
134     if (m_resourceHandle)
135     {
136         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
137                                  "Observation state can not be changed when resource is started!");
138     }
139
140     if (true == state)
141         m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
142     else
143         m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
144 }
145
146 void SimulatorSingleResourceImpl::setObserverCallback(ObserverCallback callback)
147 {
148     VALIDATE_CALLBACK(callback)
149     m_observeCallback = callback;
150 }
151
152 bool SimulatorSingleResourceImpl::isObservable()
153 {
154     return (m_property & OC_OBSERVABLE);
155 }
156
157 bool SimulatorSingleResourceImpl::isStarted()
158 {
159     return (nullptr != m_resourceHandle);
160 }
161
162 void SimulatorSingleResourceImpl::start()
163 {
164     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
165     if (m_resourceHandle)
166     {
167         SIM_LOG(ILogger::INFO, "[" << m_name << "] " << "Resource already registered!")
168     }
169
170     if (m_uri.empty() || m_resourceType.empty())
171     {
172         throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
173     }
174
175     typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
176             const std::string &, OC::EntityHandler, uint8_t);
177
178     invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
179                      m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
180                      std::bind(&SimulatorSingleResourceImpl::handleRequests,
181                                this, std::placeholders::_1), m_property);
182
183     for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
184     {
185         typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
186                 const std::string &);
187
188         try
189         {
190             invokeocplatform(static_cast<bindInterfaceToResource>(
191                                  OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
192                              m_interfaces[index]);
193         }
194         catch (SimulatorException &e)
195         {
196             stop();
197             throw;
198         }
199     }
200 }
201
202 void SimulatorSingleResourceImpl::stop()
203 {
204     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
205     if (!m_resourceHandle)
206         return;
207
208     // Stop all the update automation of this resource
209     m_updateAutomationMgr.stopAll();
210
211     // Clear all the observers
212     removeAllObservers();
213
214     // Unregister the resource from stack
215     typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
216
217     invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
218                      m_resourceHandle);
219
220     m_resourceHandle = nullptr;
221 }
222
223 std::vector<ObserverInfo> SimulatorSingleResourceImpl::getObserversList()
224 {
225     return m_observersList;
226 }
227
228 void SimulatorSingleResourceImpl::notify(int id, SimulatorResourceModel &resModel)
229 {
230     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
231     if (!m_resourceHandle)
232         return;
233
234     std::shared_ptr<OC::OCResourceResponse> resourceResponse =
235     {std::make_shared<OC::OCResourceResponse>()};
236
237     resourceResponse->setErrorCode(200);
238     resourceResponse->setResponseResult(OC_EH_OK);
239     resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
240             OC::DEFAULT_INTERFACE);
241
242     OC::ObservationIds observers;
243     observers.push_back(id);
244
245     typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
246             const std::shared_ptr<OC::OCResourceResponse>);
247
248     invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
249                      m_resourceHandle, observers, resourceResponse);
250 }
251
252 void SimulatorSingleResourceImpl::notifyAll(SimulatorResourceModel &resModel)
253 {
254     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
255     if (!m_resourceHandle)
256         return;
257
258     if (!m_observersList.size())
259         return;
260
261     std::shared_ptr<OC::OCResourceResponse> resourceResponse =
262     {std::make_shared<OC::OCResourceResponse>()};
263
264     resourceResponse->setErrorCode(200);
265     resourceResponse->setResponseResult(OC_EH_OK);
266     resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
267             OC::DEFAULT_INTERFACE);
268
269     OC::ObservationIds observers;
270     for (auto &observer : m_observersList)
271         observers.push_back(observer.id);
272
273     typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
274             const std::shared_ptr<OC::OCResourceResponse>);
275
276     invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
277                      m_resourceHandle, observers, resourceResponse);
278 }
279
280 void SimulatorSingleResourceImpl::notify(int id)
281 {
282     notify(id, m_resModel);
283 }
284
285 void SimulatorSingleResourceImpl::notifyAll()
286 {
287     notifyAll(m_resModel);
288 }
289
290 bool SimulatorSingleResourceImpl::getAttribute(const std::string &attrName,
291         SimulatorResourceModel::Attribute &attribute)
292 {
293     VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
294
295     std::lock_guard<std::mutex> lock(m_modelLock);
296     return m_resModel.getAttribute(attrName, attribute);
297 }
298
299 void SimulatorSingleResourceImpl::addAttribute(const SimulatorResourceModel::Attribute &attribute,
300         bool notify)
301 {
302     std::lock_guard<std::mutex> lock(m_modelLock);
303     if (m_resModel.containsAttribute(attribute.getName()))
304         throw SimulatorException(SIMULATOR_ERROR, "Attribute exist with same name!");
305
306     if (!m_resModel.add(attribute))
307         throw SimulatorException(SIMULATOR_ERROR, "Failed to add attribute!");
308
309     if (notify && isStarted())
310         notifyAll();
311 }
312
313 bool SimulatorSingleResourceImpl::getAttributeProperty(const std::string &attrName,
314         SimulatorResourceModel::AttributeProperty &property)
315 {
316     VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
317
318     std::lock_guard<std::mutex> lock(m_modelLock);
319     return m_resModel.getAttributeProperty(attrName, property);
320 }
321
322 bool SimulatorSingleResourceImpl::setAttributeProperty(const std::string &attrName,
323         const SimulatorResourceModel::AttributeProperty &property)
324 {
325     VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
326
327     std::lock_guard<std::mutex> lock(m_modelLock);
328     return m_resModel.setAttributeProperty(attrName, property);
329 }
330
331 bool SimulatorSingleResourceImpl::updateAttributeValue(
332     const SimulatorResourceModel::Attribute &attribute,
333     bool notify)
334 {
335     std::lock_guard<std::mutex> lock(m_modelLock);
336     if (m_resModel.updateValue(attribute))
337     {
338         if (notify && isStarted())
339             notifyAll();
340         return true;
341     }
342
343     return false;
344 }
345
346 bool SimulatorSingleResourceImpl::removeAttribute(const std::string &attrName, bool notify)
347 {
348     VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
349
350     std::lock_guard<std::mutex> lock(m_modelLock);
351     if (m_resModel.removeAttribute(attrName))
352     {
353         if (notify && isStarted())
354             notifyAll();
355         return true;
356     }
357
358     return false;
359 }
360
361 SimulatorResourceModel SimulatorSingleResourceImpl::getResourceModel()
362 {
363     std::lock_guard<std::mutex> lock(m_modelLock);
364     return m_resModel;
365 }
366
367 void SimulatorSingleResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
368 {
369     VALIDATE_CALLBACK(callback)
370     m_modelCallback = callback;
371 }
372
373 int SimulatorSingleResourceImpl::startResourceUpdation(AutomationType type,
374         int updateInterval, updateCompleteCallback callback)
375 {
376     VALIDATE_CALLBACK(callback)
377
378     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
379     if (!m_resourceHandle)
380         throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
381
382     return m_updateAutomationMgr.startResourceAutomation(this, type, updateInterval, callback);
383 }
384
385 int SimulatorSingleResourceImpl::startAttributeUpdation(const std::string &attrName,
386         AutomationType type, int updateInterval, updateCompleteCallback callback)
387 {
388     VALIDATE_CALLBACK(callback)
389
390     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
391     if (!m_resourceHandle)
392         throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
393
394     return m_updateAutomationMgr.startAttributeAutomation(this, attrName, type,
395             updateInterval, callback);
396 }
397
398 std::vector<int> SimulatorSingleResourceImpl::getResourceUpdationIds()
399 {
400     return m_updateAutomationMgr.getResourceAutomationIds();
401 }
402
403 std::vector<int> SimulatorSingleResourceImpl::getAttributeUpdationIds()
404 {
405     return m_updateAutomationMgr.getAttributeAutomationIds();
406 }
407
408 void SimulatorSingleResourceImpl::stopUpdation(const int id)
409 {
410     m_updateAutomationMgr.stop(id);
411 }
412
413 void SimulatorSingleResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
414 {
415     std::lock_guard<std::mutex> lock(m_modelLock);
416     m_resModel = resModel;
417 }
418
419 void SimulatorSingleResourceImpl::setPutErrorResponseModel(const SimulatorResourceModel &resModel)
420 {
421     m_putErrorResModel = resModel;
422 }
423
424 void SimulatorSingleResourceImpl::setPostErrorResponseModel(const SimulatorResourceModel &resModel)
425 {
426     m_postErrorResModel = resModel;
427 }
428
429 void SimulatorSingleResourceImpl::notifyApp(SimulatorResourceModel &resModel)
430 {
431     if (m_modelCallback)
432     {
433         m_modelCallback(m_uri, resModel);
434     }
435 }
436
437 void SimulatorSingleResourceImpl::notifyApp()
438 {
439     notifyApp(m_resModel);
440 }
441
442 bool SimulatorSingleResourceImpl::updateResourceModel(OC::OCRepresentation &ocRep,
443         SimulatorResourceModel &resModel)
444 {
445     std::lock_guard<std::mutex> lock(m_modelLock);
446     if (m_resModel.update(ocRep))
447     {
448         resModel = m_resModel;
449         return true;
450     }
451     return false;
452 }
453
454 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
455     std::shared_ptr<OC::OCResourceRequest> request)
456 {
457     OCEntityHandlerResult errCode = OC_EH_ERROR;
458     if (!request)
459         return OC_EH_ERROR;
460
461     if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
462     {
463         {
464             OC::OCRepresentation rep = request->getResourceRepresentation();
465             std::string payload = getPayloadString(rep);
466             SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
467                     << " request received. \n**Payload details**\n" << payload)
468         }
469
470         // Handover the request to appropriate interface handler
471         std::string interfaceType(OC::DEFAULT_INTERFACE);
472         OC::QueryParamsMap queryParams = request->getQueryParameters();
473         if (queryParams.end() != queryParams.find("if"))
474             interfaceType = queryParams["if"];
475
476         std::shared_ptr<OC::OCResourceResponse> response;
477         if (interfaceType == OC::DEFAULT_INTERFACE)
478         {
479             response = requestOnBaseLineInterface(request);
480         }
481
482         // Send response if the request handled by resource
483         if (response)
484         {
485             if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
486                 return OC_EH_ERROR;
487         }
488         else
489         {
490             SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
491             return OC_EH_ERROR;
492         }
493     }
494
495     if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
496     {
497         if (false == isObservable())
498         {
499             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
500             SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state")
501             return OC_EH_ERROR;
502         }
503
504         OC::ObservationInfo observationInfo = request->getObservationInfo();
505         if (OC::ObserveAction::ObserveRegister == observationInfo.action)
506         {
507             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
508             addObserver(observationInfo);
509         }
510         else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
511         {
512             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
513             removeObserver(observationInfo);
514         }
515         errCode = OC_EH_OK;
516     }
517
518     return errCode;
519 }
520
521 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::requestOnBaseLineInterface(
522     std::shared_ptr<OC::OCResourceRequest> request)
523 {
524     std::shared_ptr<OC::OCResourceResponse> response;
525     if ("GET" == request->getRequestType())
526     {
527         OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
528         response = std::make_shared<OC::OCResourceResponse>();
529         response->setErrorCode(200);
530         response->setResponseResult(OC_EH_OK);
531         response->setResourceRepresentation(ocRep);
532         std::string resPayload = getPayloadString(ocRep);
533         SIM_LOG(ILogger::INFO, "[" << m_uri <<
534                 "] Sending response for GET request. \n**Payload details**" << resPayload)
535     }
536     else if ("PUT" == request->getRequestType()
537              || "POST" == request->getRequestType())
538     {
539         OC::OCRepresentation requestRep = request->getResourceRepresentation();
540         SimulatorResourceModel resModel;
541         if (true == updateResourceModel(requestRep, resModel))
542         {
543             notifyAll(resModel);
544             notifyApp(resModel);
545
546             response = std::make_shared<OC::OCResourceResponse>();
547             response->setErrorCode(200);
548             response->setResponseResult(OC_EH_OK);
549             response->setResourceRepresentation(resModel.getOCRepresentation());
550             std::string resPayload = getPayloadString(resModel.getOCRepresentation());
551             SIM_LOG(ILogger::INFO, "[" << m_uri <<
552                     "] Sending response for " << request->getRequestType() << " request. \n**Payload details**" <<
553                     resPayload)
554         }
555         else
556         {
557             response = std::make_shared<OC::OCResourceResponse>();
558             response->setErrorCode(400);
559             response->setResponseResult(OC_EH_ERROR);
560             if ("PUT" == request->getRequestType())
561             {
562                 if (m_putErrorResModel.getOCRepresentation().empty())
563                     response->setResourceRepresentation(m_resModel.getOCRepresentation());
564                 else
565                     response->setResourceRepresentation(m_putErrorResModel.getOCRepresentation());
566             }
567             else
568             {
569                 if (m_postErrorResModel.getOCRepresentation().empty())
570                     response->setResourceRepresentation(m_resModel.getOCRepresentation());
571                 else
572                     response->setResourceRepresentation(m_postErrorResModel.getOCRepresentation());
573             }
574         }
575     }
576     else if ("DELETE" == request->getRequestType())
577     {
578         // TODO: Handle this request
579     }
580
581     if (response)
582     {
583         response->setRequestHandle(request->getRequestHandle());
584         response->setResourceHandle(request->getResourceHandle());
585     }
586
587     return response;
588 }
589
590 void SimulatorSingleResourceImpl::addObserver(OC::ObservationInfo ocObserverInfo)
591 {
592     ObserverInfo info {ocObserverInfo.obsId, ocObserverInfo.address, ocObserverInfo.port};
593     m_observersList.push_back(info);
594
595     if (m_observeCallback)
596         m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
597 }
598
599 void SimulatorSingleResourceImpl::removeObserver(OC::ObservationInfo ocObserverInfo)
600 {
601     ObserverInfo info;
602     for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
603     {
604         if ((info = *iter), info.id == ocObserverInfo.obsId)
605         {
606             m_observersList.erase(iter);
607             break;
608         }
609     }
610
611     if (m_observeCallback)
612         m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
613 }
614
615 void SimulatorSingleResourceImpl::removeAllObservers()
616 {
617     std::vector<ObserverInfo> observerList = m_observersList;
618     m_observersList.clear();
619     for (int index = 0; index < observerList.size(); index++)
620     {
621         if (m_observeCallback)
622             m_observeCallback(m_uri, ObservationStatus::UNREGISTER, observerList[index]);
623     }
624 }