f4f48854c229bf949c85447b3ea691b53ea8ce74
[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::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
430 {
431     m_actionTypes = actionType;
432 }
433
434 void SimulatorSingleResourceImpl::notifyApp(SimulatorResourceModel &resModel)
435 {
436     if (m_modelCallback)
437     {
438         m_modelCallback(m_uri, resModel);
439     }
440 }
441
442 void SimulatorSingleResourceImpl::notifyApp()
443 {
444     notifyApp(m_resModel);
445 }
446
447 bool SimulatorSingleResourceImpl::updateResourceModel(OC::OCRepresentation &ocRep,
448         SimulatorResourceModel &resModel)
449 {
450     std::lock_guard<std::mutex> lock(m_modelLock);
451     if (m_resModel.update(ocRep))
452     {
453         resModel = m_resModel;
454         return true;
455     }
456     return false;
457 }
458
459 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
460     std::shared_ptr<OC::OCResourceRequest> request)
461 {
462     OCEntityHandlerResult errCode = OC_EH_ERROR;
463     if (!request)
464         return OC_EH_ERROR;
465
466     if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
467     {
468         {
469             OC::OCRepresentation rep = request->getResourceRepresentation();
470             std::string payload = getPayloadString(rep);
471             SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
472                     << " request received. \n**Payload details**\n" << payload)
473         }
474
475         // TODO: Handover the request to appropriate interface handler
476
477         std::shared_ptr<OC::OCResourceResponse> response;
478         response = requestOnBaseLineInterface(request);
479
480         // Send response if the request handled by resource
481         if (response)
482         {
483             if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
484                 return OC_EH_ERROR;
485         }
486         else
487         {
488             SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
489             return OC_EH_ERROR;
490         }
491     }
492
493     if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
494     {
495         if (false == isObservable())
496         {
497             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
498             SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state")
499             return OC_EH_ERROR;
500         }
501
502         OC::ObservationInfo observationInfo = request->getObservationInfo();
503         if (OC::ObserveAction::ObserveRegister == observationInfo.action)
504         {
505             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
506             addObserver(observationInfo);
507         }
508         else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
509         {
510             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
511             removeObserver(observationInfo);
512         }
513         errCode = OC_EH_OK;
514     }
515
516     return errCode;
517 }
518
519 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::requestOnBaseLineInterface(
520     std::shared_ptr<OC::OCResourceRequest> request)
521 {
522     std::shared_ptr<OC::OCResourceResponse> response;
523
524     RAML::ActionType type = getActionType(request->getRequestType());
525
526     if (!m_actionTypes.empty())
527     {
528         if (m_actionTypes.end() == m_actionTypes.find(type))
529             return response;
530     }
531
532     if ("GET" == request->getRequestType())
533     {
534         OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
535         response = std::make_shared<OC::OCResourceResponse>();
536         response->setErrorCode(200);
537         response->setResponseResult(OC_EH_OK);
538         response->setResourceRepresentation(ocRep);
539         std::string resPayload = getPayloadString(ocRep);
540         SIM_LOG(ILogger::INFO, "[" << m_uri <<
541                 "] Sending response for GET request. \n**Payload details**" << resPayload)
542     }
543     else if ("PUT" == request->getRequestType()
544              || "POST" == request->getRequestType())
545     {
546         OC::OCRepresentation requestRep = request->getResourceRepresentation();
547         SimulatorResourceModel resModel;
548         if (true == updateResourceModel(requestRep, resModel))
549         {
550             notifyAll(resModel);
551             notifyApp(resModel);
552
553             response = std::make_shared<OC::OCResourceResponse>();
554             response->setErrorCode(200);
555             response->setResponseResult(OC_EH_OK);
556             response->setResourceRepresentation(resModel.getOCRepresentation());
557             std::string resPayload = getPayloadString(resModel.getOCRepresentation());
558             SIM_LOG(ILogger::INFO, "[" << m_uri <<
559                     "] Sending response for " << request->getRequestType() << " request. \n**Payload details**" <<
560                     resPayload)
561         }
562         else
563         {
564             response = std::make_shared<OC::OCResourceResponse>();
565             response->setErrorCode(403);
566             response->setResponseResult(OC_EH_ERROR);
567             if ("PUT" == request->getRequestType())
568             {
569                 if (m_putErrorResModel.getOCRepresentation().empty())
570                     response->setResourceRepresentation(m_resModel.getOCRepresentation());
571                 else
572                     response->setResourceRepresentation(m_putErrorResModel.getOCRepresentation());
573             }
574             else
575             {
576                 if (m_postErrorResModel.getOCRepresentation().empty())
577                     response->setResourceRepresentation(m_resModel.getOCRepresentation());
578                 else
579                     response->setResourceRepresentation(m_postErrorResModel.getOCRepresentation());
580             }
581         }
582     }
583     else if ("DELETE" == request->getRequestType())
584     {
585         // TODO: Handle this request
586     }
587
588     if (response)
589     {
590         response->setRequestHandle(request->getRequestHandle());
591         response->setResourceHandle(request->getResourceHandle());
592     }
593
594     return response;
595 }
596
597 void SimulatorSingleResourceImpl::addObserver(OC::ObservationInfo ocObserverInfo)
598 {
599     ObserverInfo info {ocObserverInfo.obsId, ocObserverInfo.address, ocObserverInfo.port};
600     m_observersList.push_back(info);
601
602     if (m_observeCallback)
603         m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
604 }
605
606 void SimulatorSingleResourceImpl::removeObserver(OC::ObservationInfo ocObserverInfo)
607 {
608     ObserverInfo info;
609     for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
610     {
611         if ((info = *iter), info.id == ocObserverInfo.obsId)
612         {
613             m_observersList.erase(iter);
614             break;
615         }
616     }
617
618     if (m_observeCallback)
619         m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
620 }
621
622 void SimulatorSingleResourceImpl::removeAllObservers()
623 {
624     std::vector<ObserverInfo> observerList = m_observersList;
625     m_observersList.clear();
626     for (int index = 0; index < observerList.size(); index++)
627     {
628         if (m_observeCallback)
629             m_observeCallback(m_uri, ObservationStatus::UNREGISTER, observerList[index]);
630     }
631 }
632
633 RAML::ActionType SimulatorSingleResourceImpl::getActionType(std::string requestType)
634 {
635     if (!requestType.compare("GET"))
636         return RAML::ActionType::GET;
637
638     if (!requestType.compare("PUT"))
639         return RAML::ActionType::PUT;
640
641     if (!requestType.compare("POST"))
642         return RAML::ActionType::POST;
643
644     if (!requestType.compare("DELETE"))
645         return RAML::ActionType::DELETE;
646
647     return RAML::ActionType::NONE;
648 }