Fix for SVACE and Klocwork issues.
[platform/upstream/iotivity.git] / service / simulator / src / client / simulator_remote_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_remote_resource_impl.h"
22 #include "request_model_builder.h"
23 #include "simulator_exceptions.h"
24 #include "simulator_utils.h"
25 #include "simulator_logger.h"
26 #include "logger.h"
27
28 #define TAG "SIMULATOR_REMOTE_RESOURCE"
29
30 static std::string requestTypeToString(RequestType type)
31 {
32     switch (type)
33     {
34         case RequestType::RQ_TYPE_GET:
35             return "GET";
36         case RequestType::RQ_TYPE_PUT:
37             return "PUT";
38         case RequestType::RQ_TYPE_POST:
39             return "POST";
40         case RequestType::RQ_TYPE_DELETE:
41             return "DELETE";
42         default:
43             return "";
44     }
45
46     return ""; // Control should not reach here
47 }
48
49 static RequestType requestTypeToEnum(const std::string &type)
50 {
51     if (type == "GET")
52     {
53         return RequestType::RQ_TYPE_GET;
54     }
55     else if (type == "PUT")
56     {
57         return RequestType::RQ_TYPE_PUT;
58     }
59     else if (type == "POST")
60     {
61         return RequestType::RQ_TYPE_POST;
62     }
63     else if (type == "DELETE")
64     {
65         return RequestType::RQ_TYPE_DELETE;
66     }
67
68     return RequestType::RQ_TYPE_UNKNOWN;
69 }
70
71 SimulatorRemoteResourceImpl::SimulatorRemoteResourceImpl(
72     const std::shared_ptr<OC::OCResource> &ocResource)
73     :   m_observeState(false),
74         m_getRequestSender(ocResource),
75         m_putRequestSender(ocResource),
76         m_postRequestSender(ocResource),
77         m_requestAutomationMngr(ocResource),
78         m_ocResource(ocResource)
79 {
80     m_id = m_ocResource->sid().append(m_ocResource->uri());
81 }
82
83 std::string SimulatorRemoteResourceImpl::getURI() const
84 {
85     return m_ocResource->uri();
86 }
87
88 std::string SimulatorRemoteResourceImpl::getHost() const
89 {
90     return m_ocResource->host();
91 }
92
93 std::string SimulatorRemoteResourceImpl::getID() const
94 {
95     return m_id;
96 }
97
98 SimulatorConnectivityType SimulatorRemoteResourceImpl::getConnectivityType() const
99 {
100     return convertConnectivityType(m_ocResource->connectivityType());
101 }
102
103 std::vector < std::string > SimulatorRemoteResourceImpl::getResourceTypes() const
104 {
105     return m_ocResource->getResourceTypes();
106 }
107
108 std::vector < std::string > SimulatorRemoteResourceImpl::getInterface() const
109 {
110     return m_ocResource->getResourceInterfaces();
111 }
112
113 bool SimulatorRemoteResourceImpl::isObservable() const
114 {
115     return m_ocResource->isObservable();
116 }
117
118 void SimulatorRemoteResourceImpl::observe(ObserveType type,
119         ObserveNotificationCallback callback)
120 {
121     VALIDATE_CALLBACK(callback)
122
123     std::lock_guard<std::mutex> lock(m_observeLock);
124     if (m_observeState)
125     {
126         OC_LOG(ERROR, TAG, "Resource is already being observed!");
127         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Resource is already being observed!")
128
129         throw SimulatorException(SIMULATOR_ERROR, "Resource is already being observed!");
130     }
131
132     OC::ObserveCallback observeCallback = std::bind(
133             [](const OC::HeaderOptions & headerOptions, const OC::OCRepresentation & ocRep,
134                const int errorCode, const int sqNum, std::string id, ObserveNotificationCallback callback)
135     {
136         SIM_LOG(ILogger::INFO, "Response received for OBSERVE request."
137                 << "\n" << getPayloadString(ocRep))
138
139         SimulatorResourceModel resourceModel = SimulatorResourceModel::build(ocRep);
140         callback(id, static_cast<SimulatorResult>(errorCode), resourceModel, sqNum);
141     }, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4,
142     m_id, callback);
143
144     OC::ObserveType observeType = OC::ObserveType::Observe;
145     if (type == ObserveType::OBSERVE_ALL)
146         observeType = OC::ObserveType::ObserveAll;
147
148     try
149     {
150         OCStackResult ocResult = m_ocResource->observe(observeType, OC::QueryParamsMap(), observeCallback);
151         if (OC_STACK_OK != ocResult)
152             throw SimulatorException(static_cast<SimulatorResult>(ocResult), OC::OCException::reason(ocResult));
153
154         SIM_LOG(ILogger::INFO, "[URI: " << getURI() << "] Sent OBSERVE request.")
155     }
156     catch (OC::OCException &e)
157     {
158         throw SimulatorException(static_cast<SimulatorResult>(e.code()), e.reason());
159     }
160
161     m_observeState = true;
162 }
163
164 void SimulatorRemoteResourceImpl::cancelObserve()
165 {
166     try
167     {
168         OCStackResult ocResult = m_ocResource->cancelObserve(OC::QualityOfService::HighQos);
169         if (OC_STACK_OK != ocResult)
170         {
171             OC_LOG(ERROR, TAG, "Cancelling observe failed!");
172             SIM_LOG(ILogger::INFO, "[URI: " << getURI() << "] Sending OBSERVE cancel request failed!")
173
174             throw SimulatorException(static_cast<SimulatorResult>(ocResult),
175                                      OC::OCException::reason(ocResult));
176         }
177
178         SIM_LOG(ILogger::INFO, "[URI: " << getURI() << "] Sent OBSERVE cancel request.")
179     }
180     catch (OC::OCException &e)
181     {
182         throw SimulatorException(static_cast<SimulatorResult>(e.code()), e.reason());
183     }
184
185     std::lock_guard<std::mutex> lock(m_observeLock);
186     m_observeState = false;
187 }
188
189 void SimulatorRemoteResourceImpl::get(const GetResponseCallback &callback)
190 {
191     VALIDATE_CALLBACK(callback)
192
193     SimulatorResult result = m_getRequestSender.send(std::bind(
194                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
195                                  std::placeholders::_2, std::placeholders::_3, callback));
196
197     if (SIMULATOR_OK != result)
198     {
199         OC_LOG(ERROR, TAG, "Failed to send GET request!");
200         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send GET request!")
201
202         throw SimulatorException(result, "Failed to send GET request!");
203     }
204 }
205
206 void SimulatorRemoteResourceImpl::get(const std::map<std::string, std::string> &queryParams,
207                                       const GetResponseCallback &callback)
208 {
209     VALIDATE_CALLBACK(callback)
210
211     SimulatorResult result = m_getRequestSender.send(queryParams, std::bind(
212                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
213                                  std::placeholders::_2, std::placeholders::_3, callback));
214
215     if (SIMULATOR_OK != result)
216     {
217         OC_LOG(ERROR, TAG, "Failed to send GET request!");
218         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send GET request!")
219
220         throw SimulatorException(result, "Failed to send GET request!");
221     }
222 }
223
224 void SimulatorRemoteResourceImpl::get(const std::string &interfaceType,
225                                       const std::map<std::string, std::string> &queryParams,
226                                       const GetResponseCallback &callback)
227 {
228     VALIDATE_CALLBACK(callback)
229
230     std::map<std::string, std::string> queryParamsCpy = queryParams;
231     if (!interfaceType.empty() && queryParamsCpy.end() == queryParamsCpy.find("if"))
232     {
233         queryParamsCpy["if"] = interfaceType;
234     }
235
236     SimulatorResult result = m_getRequestSender.send(queryParamsCpy, std::bind(
237                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
238                                  std::placeholders::_2, std::placeholders::_3, callback));
239
240     if (SIMULATOR_OK != result)
241     {
242         OC_LOG(ERROR, TAG, "Failed to send GET request!");
243         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send GET request!")
244
245         throw SimulatorException(result, "Failed to send GET request!");
246     }
247 }
248
249 void SimulatorRemoteResourceImpl::put(const SimulatorResourceModel &representation,
250                                       const PutResponseCallback &callback)
251 {
252     VALIDATE_CALLBACK(callback)
253
254     SimulatorResult result = m_putRequestSender.send(representation, std::bind(
255                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
256                                  std::placeholders::_2, std::placeholders::_3, callback));
257
258     if (SIMULATOR_OK != result)
259     {
260         OC_LOG(ERROR, TAG, "Failed to send PUT request!");
261         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send PUT request!")
262
263         throw SimulatorException(result, "Failed to send PUT request!");
264     }
265 }
266
267 void SimulatorRemoteResourceImpl::put(const std::map<std::string, std::string> &queryParams,
268                                       const SimulatorResourceModel &representation,
269                                       const PutResponseCallback &callback)
270 {
271     VALIDATE_CALLBACK(callback)
272
273     SimulatorResult result = m_putRequestSender.send(queryParams, representation, std::bind(
274                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
275                                  std::placeholders::_2, std::placeholders::_3, callback));
276
277     if (SIMULATOR_OK != result)
278     {
279         OC_LOG(ERROR, TAG, "Failed to send PUT request!");
280         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send PUT request!")
281
282         throw SimulatorException(result, "Failed to send PUT request!");
283     }
284 }
285
286 void SimulatorRemoteResourceImpl::put(const std::string &interfaceType,
287                                       const std::map<std::string, std::string> &queryParams,
288                                       const SimulatorResourceModel &representation,
289                                       const PutResponseCallback &callback)
290 {
291     VALIDATE_CALLBACK(callback)
292
293     std::map<std::string, std::string> queryParamsCpy = queryParams;
294     if (!interfaceType.empty() && queryParamsCpy.end() == queryParamsCpy.find("if"))
295     {
296         queryParamsCpy["if"] = interfaceType;
297     }
298
299     SimulatorResult result = m_putRequestSender.send(queryParamsCpy, representation, std::bind(
300                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
301                                  std::placeholders::_2, std::placeholders::_3, callback));
302
303     if (SIMULATOR_OK != result)
304     {
305         OC_LOG(ERROR, TAG, "Failed to send PUT request!");
306         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send PUT request!")
307
308         throw SimulatorException(result, "Failed to send PUT request!");
309     }
310 }
311
312 void SimulatorRemoteResourceImpl::post(const SimulatorResourceModel &representation,
313                                        const PostResponseCallback &callback)
314 {
315     VALIDATE_CALLBACK(callback)
316
317     SimulatorResult result = m_postRequestSender.send(representation, std::bind(
318                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
319                                  std::placeholders::_2, std::placeholders::_3, callback));
320
321     if (SIMULATOR_OK != result)
322     {
323         OC_LOG(ERROR, TAG, "Failed to send POST request!");
324         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send POST request!")
325
326         throw SimulatorException(result, "Failed to send POST request!");
327     }
328 }
329
330 void SimulatorRemoteResourceImpl::post(const std::map<std::string, std::string> &queryParams,
331                                        const SimulatorResourceModel &representation,
332                                        const PostResponseCallback &callback)
333 {
334     VALIDATE_CALLBACK(callback)
335
336     SimulatorResult result = m_postRequestSender.send(queryParams, representation, std::bind(
337                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
338                                  std::placeholders::_2, std::placeholders::_3, callback));
339
340     if (SIMULATOR_OK != result)
341     {
342         OC_LOG(ERROR, TAG, "Failed to send POST request!");
343         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send POST request!")
344
345         throw SimulatorException(result, "Failed to send POST request!");
346     }
347 }
348
349 void SimulatorRemoteResourceImpl::post(const std::string &interfaceType,
350                                        const std::map<std::string, std::string> &queryParams,
351                                        const SimulatorResourceModel &representation,
352                                        const PostResponseCallback &callback)
353 {
354     VALIDATE_CALLBACK(callback)
355
356     std::map<std::string, std::string> queryParamsCpy = queryParams;
357     if (!interfaceType.empty() && queryParamsCpy.end() == queryParamsCpy.find("if"))
358     {
359         queryParamsCpy["if"] = interfaceType;
360     }
361
362     SimulatorResult result = m_postRequestSender.send(queryParamsCpy, representation, std::bind(
363                                  &SimulatorRemoteResourceImpl::onResponseReceived, this, std::placeholders::_1,
364                                  std::placeholders::_2, std::placeholders::_3, callback));
365
366     if (SIMULATOR_OK != result)
367     {
368         OC_LOG(ERROR, TAG, "Failed to send POST request!");
369         SIM_LOG(ILogger::ERROR, "[URI: " << getURI() << "] Failed to send POST request!")
370
371         throw SimulatorException(result, "Failed to send POST request!");
372     }
373 }
374
375 std::map<RequestType, SimulatorRequestModel>
376 SimulatorRemoteResourceImpl::configure(const std::string &path)
377 {
378     VALIDATE_INPUT(path.empty(), "Path is empty!")
379
380     try
381     {
382         std::shared_ptr<RAML::RamlParser> ramlParser =
383             std::make_shared<RAML::RamlParser>(path);
384         RAML::RamlPtr raml = ramlParser->getRamlPtr();
385
386         m_requestModels = RequestModelBuilder().build(raml, m_ocResource->uri());
387     }
388     catch (RAML::RamlException &e)
389     {
390         throw SimulatorException(SIMULATOR_ERROR, "Failed to configure resource!");
391     }
392
393     std::map<RequestType, SimulatorRequestModel> requestModels;
394     for (auto &requestModelEntry : m_requestModels)
395     {
396         RequestType requestType = requestTypeToEnum(requestModelEntry.first);
397         SimulatorRequestModel requestModel(requestType);
398         requestModel.setQueryParams((requestModelEntry.second)->getQueryParams());
399         requestModel.setRequestBodySchema((requestModelEntry.second)->getRequestRepSchema());
400
401         requestModels[requestType] = requestModel;
402     }
403
404     return requestModels;
405 }
406
407 int SimulatorRemoteResourceImpl::startAutoRequesting(RequestType type,
408         AutoRequestGenerationCallback callback)
409 {
410     VALIDATE_CALLBACK(callback)
411
412     // Check if resource supports request type
413     std::string requestType = requestTypeToString(type);
414     if (m_requestModels.end() == m_requestModels.find(requestType))
415     {
416         OC_LOG(ERROR, TAG, "Resource is not configured for this request type!");
417         throw NoSupportException("Resource is not configured for this request type!");
418     }
419
420     std::shared_ptr<RequestModel> requestModel = m_requestModels[requestType];
421     switch (type)
422     {
423         case RequestType::RQ_TYPE_GET:
424             return m_requestAutomationMngr.startOnGET(requestModel,
425                     std::bind(&SimulatorRemoteResourceImpl::onAutoRequestingState, this,
426                               std::placeholders::_1, std::placeholders::_2, callback));
427
428         case RequestType::RQ_TYPE_PUT:
429             return m_requestAutomationMngr.startOnPUT(requestModel,
430                     std::bind(&SimulatorRemoteResourceImpl::onAutoRequestingState, this,
431                               std::placeholders::_1, std::placeholders::_2, callback));
432
433         case RequestType::RQ_TYPE_POST:
434             return m_requestAutomationMngr.startOnPOST(requestModel,
435                     std::bind(&SimulatorRemoteResourceImpl::onAutoRequestingState, this,
436                               std::placeholders::_1, std::placeholders::_2, callback));
437
438         case RequestType::RQ_TYPE_DELETE:
439         default:
440             throw NoSupportException("Not implemented!");
441     }
442
443     return -1; // Code should not reach here
444 }
445
446 void SimulatorRemoteResourceImpl::stopAutoRequesting(int id)
447 {
448     m_requestAutomationMngr.stop(id);
449 }
450
451 void SimulatorRemoteResourceImpl::onResponseReceived(SimulatorResult result,
452         const SimulatorResourceModel &resourceModel, const RequestInfo &reqInfo,
453         ResponseCallback callback)
454 {
455     callback(m_id, result, resourceModel);
456 }
457
458 void SimulatorRemoteResourceImpl::onAutoRequestingState(int sessionId, OperationState state,
459         AutoRequestGenerationCallback callback)
460 {
461     callback(m_id, sessionId, state);
462 }
463
464 SimulatorConnectivityType SimulatorRemoteResourceImpl::convertConnectivityType(
465     OCConnectivityType type) const
466 {
467     switch (type)
468     {
469         case CT_ADAPTER_IP:
470             return SIMULATOR_CT_ADAPTER_IP;
471
472         case CT_IP_USE_V4:
473             return SIMULATOR_CT_IP_USE_V4 ;
474
475         case CT_IP_USE_V6:
476             return SIMULATOR_CT_IP_USE_V6;
477
478         case CT_ADAPTER_GATT_BTLE:
479             return SIMULATOR_CT_ADAPTER_GATT_BTLE;
480
481         case CT_ADAPTER_RFCOMM_BTEDR:
482             return SIMULATOR_CT_ADAPTER_RFCOMM_BTEDR;
483
484         default:
485             return SIMULATOR_CT_DEFAULT;
486     }
487 }