Merge "Fix Memory leak of getResourceType() in ocstack.c"
[platform/upstream/iotivity.git] / resource / src / InProcServerWrapper.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH 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 <random>
22 #include <cstring>
23 #include <cstdlib>
24 #include <iostream>
25 #include <algorithm>
26 #include <map>
27 #include <sstream>
28 #include <string>
29
30 #include <InProcServerWrapper.h>
31 #include <InitializeException.h>
32 #include <OCResourceRequest.h>
33 #include <OCResourceResponse.h>
34 #include <ocstack.h>
35 #include <OCApi.h>
36 #include <OCPlatform.h>
37 #include <OCUtilities.h>
38
39 using namespace std;
40 using namespace OC;
41
42 namespace OC
43 {
44     namespace details
45     {
46         std::mutex serverWrapperLock;
47         std::map <OCResourceHandle, OC::EntityHandler>  entityHandlerMap;
48         std::map <OCResourceHandle, std::string> resourceUriMap;
49         EntityHandler defaultDeviceEntityHandler = 0;
50     }
51 }
52
53 void formResourceRequest(OCEntityHandlerFlag flag,
54                          OCEntityHandlerRequest * entityHandlerRequest,
55                          std::shared_ptr<OCResourceRequest> pRequest)
56 {
57     pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
58     pRequest->setResourceHandle(entityHandlerRequest->resource);
59
60     if(flag & OC_INIT_FLAG)
61     {
62         pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
63     }
64
65     if(flag & OC_REQUEST_FLAG)
66     {
67         pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
68
69         if(entityHandlerRequest)
70         {
71             if(entityHandlerRequest->query)
72             {
73                 std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
74
75                 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
76
77                 if(qp.size() > 0)
78                 {
79                     pRequest->setQueryParams(qp);
80                 }
81             }
82             if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
83             {
84                 //Set the header options here.
85                 uint16_t optionID;
86                 std::string optionData;
87                 HeaderOptions headerOptions;
88
89                 for(int i = 0;
90                     i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
91                     i++)
92                 {
93                     optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
94                     optionData = reinterpret_cast<const char*>
95                              (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
96                     HeaderOption::OCHeaderOption headerOption(optionID, optionData);
97                     headerOptions.push_back(headerOption);
98                 }
99                 pRequest->setHeaderOptions(headerOptions);
100             }
101
102             if(OC_REST_GET == entityHandlerRequest->method)
103             {
104                 pRequest->setRequestType(OC::PlatformCommands::GET);
105             }
106             else if(OC_REST_PUT == entityHandlerRequest->method)
107             {
108                 pRequest->setRequestType(OC::PlatformCommands::PUT);
109                 pRequest->setPayload(std::string(reinterpret_cast<const char*>
110                                             (entityHandlerRequest->reqJSONPayload)));
111             }
112             else if(OC_REST_POST == entityHandlerRequest->method)
113             {
114                 pRequest->setRequestType(OC::PlatformCommands::POST);
115                 pRequest->setPayload(std::string(reinterpret_cast<const char*>
116                                             (entityHandlerRequest->reqJSONPayload)));
117             }
118             else if(OC_REST_DELETE == entityHandlerRequest->method)
119             {
120                 pRequest->setRequestType(OC::PlatformCommands::DELETE);
121             }
122         }
123     }
124
125     if(flag & OC_OBSERVE_FLAG)
126     {
127         pRequest->setRequestHandlerFlag(
128                    OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
129
130         if(entityHandlerRequest)
131         {
132             OC::ObservationInfo observationInfo;
133             observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
134             observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
135             pRequest->setObservationInfo(observationInfo);
136         }
137     }
138 }
139
140 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
141                                                   OCEntityHandlerRequest * entityHandlerRequest,
142                                                   char* uri)
143 {
144     OCEntityHandlerResult result = OC_EH_ERROR;
145
146     OC::oclog() << "In Default device entity handler wrapper";
147
148     if(NULL == entityHandlerRequest)
149     {
150         oclog() << "Entity handler request is NULL.";
151         return OC_EH_ERROR;
152     }
153
154     auto pRequest = std::make_shared<OC::OCResourceRequest>();
155
156     formResourceRequest(flag, entityHandlerRequest, pRequest);
157
158     pRequest->setResourceUri(std::string(uri));
159
160     EntityHandler defHandler;
161     {
162         std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
163         defHandler = OC::details::defaultDeviceEntityHandler;
164     }
165
166     if(defHandler)
167     {
168         result = defHandler(pRequest);
169     }
170     else
171     {
172         oclog() << "Default device entity handler was not set.";
173         return OC_EH_ERROR;
174     }
175
176     return result;
177 }
178
179
180 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
181                                            OCEntityHandlerRequest * entityHandlerRequest)
182 {
183     OCEntityHandlerResult result = OC_EH_ERROR;
184
185     oclog() << "\nIn entity handler wrapper: " << endl;
186
187     if(NULL == entityHandlerRequest)
188     {
189         oclog() << "Entity handler request is NULL."  << endl;
190         return OC_EH_ERROR;
191     }
192
193     auto pRequest = std::make_shared<OC::OCResourceRequest>();
194
195     formResourceRequest(flag, entityHandlerRequest, pRequest);
196
197     std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
198     std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
199     {
200         std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
201         resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
202         resourceUriEnd = OC::details::resourceUriMap.end();
203     }
204     // Finding the corresponding URI for a resource handle and set the URI in the request
205     if(resourceUriEntry != resourceUriEnd)
206     {
207         pRequest->setResourceUri(resourceUriEntry->second);
208     }
209     else
210     {
211         oclog() << "Resource handle not found; Resource URI not set in request";
212         return OC_EH_ERROR;
213     }
214
215     std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
216     std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
217     {
218         // Finding the corresponding CPP Application entityHandler for a given resource
219         std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
220         entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
221         entityHandlerEnd = OC::details::entityHandlerMap.end();
222     }
223
224     if(entityHandlerEntry != entityHandlerEnd)
225     {
226         // Call CPP Application Entity Handler
227         if(entityHandlerEntry->second)
228         {
229             result = entityHandlerEntry->second(pRequest);
230         }
231         else
232         {
233             oclog() << "C stack should not call again for parent resource\n";
234             return OC_EH_ERROR;
235         }
236     }
237     else
238     {
239         oclog() << "No entity handler found."  << endl;
240         return OC_EH_ERROR;
241     }
242
243     return result;
244 }
245
246 namespace OC
247 {
248     InProcServerWrapper::InProcServerWrapper(
249         std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
250      : m_csdkLock(csdkLock)
251     {
252         OCMode initType;
253
254         if(cfg.mode == ModeType::Server)
255         {
256             initType = OC_SERVER;
257         }
258         else if (cfg.mode == ModeType::Both)
259         {
260             initType = OC_CLIENT_SERVER;
261         }
262         else
263         {
264             throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
265                                       OC_STACK_INVALID_PARAM);
266         }
267
268         OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
269
270         if(OC_STACK_OK != result)
271         {
272             throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
273         }
274
275         m_threadRun = true;
276         m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
277     }
278
279     void InProcServerWrapper::processFunc()
280     {
281         auto cLock = m_csdkLock.lock();
282         while(cLock && m_threadRun)
283         {
284             OCStackResult result;
285
286             {
287                 std::lock_guard<std::recursive_mutex> lock(*cLock);
288                 result = OCProcess();
289             }
290
291             // ...the value of variable result is simply ignored for now.
292             if(OC_STACK_ERROR == result)
293              ;
294
295             std::this_thread::sleep_for(std::chrono::milliseconds(10));
296         }
297     }
298
299     OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
300     {
301         auto cLock = m_csdkLock.lock();
302         OCStackResult result = OC_STACK_ERROR;
303         if(cLock)
304         {
305             std::lock_guard<std::recursive_mutex> lock(*cLock);
306             result = OCSetDeviceInfo(deviceInfo);
307         }
308         return result;
309     }
310
311     OCStackResult InProcServerWrapper::registerResource(
312                     OCResourceHandle& resourceHandle,
313                     std::string& resourceURI,
314                     const std::string& resourceTypeName,
315                     const std::string& resourceInterface,
316                     EntityHandler& eHandler,
317                     uint8_t resourceProperties)
318
319     {
320         OCStackResult result = OC_STACK_ERROR;
321
322         auto cLock = m_csdkLock.lock();
323
324         if(cLock)
325         {
326             std::lock_guard<std::recursive_mutex> lock(*cLock);
327
328             if(NULL != eHandler)
329             {
330                 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
331                             resourceTypeName.c_str(), // const char * resourceTypeName
332                             resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
333                             resourceURI.c_str(), // const char * uri
334                             EntityHandlerWrapper, // OCEntityHandler entityHandler
335                             resourceProperties // uint8_t resourceProperties
336                             );
337             }
338             else
339             {
340                 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
341                             resourceTypeName.c_str(), // const char * resourceTypeName
342                             resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
343                             resourceURI.c_str(), // const char * uri
344                             NULL, // OCEntityHandler entityHandler
345                             resourceProperties // uint8_t resourceProperties
346                             );
347             }
348
349             if(result != OC_STACK_OK)
350             {
351                 resourceHandle = (OCResourceHandle) 0;
352             }
353             else
354             {
355                 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
356                 OC::details::entityHandlerMap[resourceHandle] = eHandler;
357                 OC::details::resourceUriMap[resourceHandle] = resourceURI;
358             }
359         }
360         else
361         {
362             result = OC_STACK_ERROR;
363         }
364
365         return result;
366     }
367
368     OCStackResult InProcServerWrapper::registerResourceWithHost(
369                     OCResourceHandle& resourceHandle,
370                     std::string& resourceHOST,
371                     std::string& resourceURI,
372                     const std::string& resourceTypeName,
373                     const std::string& resourceInterface,
374                     EntityHandler& eHandler,
375                     uint8_t resourceProperties)
376
377     {
378         OCStackResult result = OC_STACK_ERROR;
379
380         auto cLock = m_csdkLock.lock();
381
382         if (cLock)
383         {
384             std::lock_guard < std::recursive_mutex > lock(*cLock);
385
386             if (NULL != eHandler)
387             {
388                 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
389                         resourceTypeName.c_str(), // const char * resourceTypeName
390                         resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
391                         resourceHOST.c_str(), // const char * host
392                         (resourceHOST + resourceURI).c_str(), // const char * uri
393                         EntityHandlerWrapper, // OCEntityHandler entityHandler
394                         resourceProperties // uint8_t resourceProperties
395                         );
396             }
397             else
398             {
399                 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
400                         resourceTypeName.c_str(), // const char * resourceTypeName
401                         resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
402                         resourceHOST.c_str(), // const char * host
403                         (resourceHOST + resourceURI).c_str(), // const char * uri
404                         nullptr, // OCEntityHandler entityHandler
405                         resourceProperties // uint8_t resourceProperties
406                         );
407             }
408
409             if (result != OC_STACK_OK)
410             {
411                 resourceHandle = nullptr;
412             }
413             else
414             {
415                 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
416                 OC::details::entityHandlerMap[resourceHandle] = eHandler;
417                 OC::details::resourceUriMap[resourceHandle] = resourceURI;
418             }
419         }
420         else
421         {
422             result = OC_STACK_ERROR;
423         }
424
425         return result;
426     }
427
428     OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
429                                         (EntityHandler entityHandler)
430     {
431         OCStackResult result = OC_STACK_ERROR;
432
433         {
434             std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
435             OC::details::defaultDeviceEntityHandler = entityHandler;
436         }
437
438         if(entityHandler)
439         {
440             result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
441         }
442         else
443         {
444             // If Null passed we unset
445             result = OCSetDefaultDeviceEntityHandler(NULL);
446         }
447
448         return result;
449     }
450
451     OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
452     {
453         auto cLock = m_csdkLock.lock();
454         OCStackResult result = OC_STACK_ERROR;
455
456         if(cLock)
457         {
458             std::lock_guard<std::recursive_mutex> lock(*cLock);
459             result = OCDeleteResource(resourceHandle);
460
461             if(result == OC_STACK_OK)
462             {
463                 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
464                 OC::details::resourceUriMap.erase(resourceHandle);
465             }
466             else
467             {
468                 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
469             }
470         }
471         else
472         {
473             result = OC_STACK_ERROR;
474         }
475
476         return result;
477     }
478
479     OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
480                      const std::string& resourceTypeName)
481     {
482         auto cLock = m_csdkLock.lock();
483         OCStackResult result;
484         if(cLock)
485         {
486             std::lock_guard<std::recursive_mutex> lock(*cLock);
487             result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
488         }
489         else
490         {
491             result = OC_STACK_ERROR;
492         }
493
494         if (result != OC_STACK_OK)
495         {
496             throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
497         }
498         return result;
499     }
500
501     OCStackResult InProcServerWrapper::bindInterfaceToResource(
502                      const OCResourceHandle& resourceHandle,
503                      const std::string& resourceInterfaceName)
504     {
505         auto cLock = m_csdkLock.lock();
506         OCStackResult result;
507         if(cLock)
508         {
509             std::lock_guard<std::recursive_mutex> lock(*cLock);
510             result = OCBindResourceInterfaceToResource(resourceHandle,
511                         resourceInterfaceName.c_str());
512         }
513         else
514         {
515             result = OC_STACK_ERROR;
516         }
517
518         if (result != OC_STACK_OK)
519         {
520             throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
521         }
522         return result;
523     }
524
525     OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
526     {
527         auto cLock = m_csdkLock.lock();
528         OCStackResult result = OC_STACK_ERROR;
529         if(cLock)
530         {
531             std::lock_guard<std::recursive_mutex> lock(*cLock);
532             result = OCStartPresence(seconds);
533         }
534
535         if(result != OC_STACK_OK)
536         {
537             throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
538         }
539         return result;
540     }
541
542     OCStackResult InProcServerWrapper::stopPresence()
543     {
544         auto cLock = m_csdkLock.lock();
545         OCStackResult result = OC_STACK_ERROR;
546         if(cLock)
547         {
548             std::lock_guard<std::recursive_mutex> lock(*cLock);
549             result = OCStopPresence();
550         }
551
552         if(result != OC_STACK_OK)
553         {
554             throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
555         }
556         return result;
557     }
558
559     OCStackResult InProcServerWrapper::sendResponse(
560         const std::shared_ptr<OCResourceResponse> pResponse)
561     {
562         auto cLock = m_csdkLock.lock();
563         OCStackResult result = OC_STACK_ERROR;
564
565         if(!pResponse)
566         {
567             result = OC_STACK_MALFORMED_RESPONSE;
568             throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
569         }
570         else
571         {
572             OCEntityHandlerResponse response;
573             std::string payLoad;
574             HeaderOptions serverHeaderOptions;
575
576             payLoad = pResponse->getPayload();
577             serverHeaderOptions = pResponse->getHeaderOptions();
578
579             response.requestHandle = pResponse->getRequestHandle();
580             response.resourceHandle = pResponse->getResourceHandle();
581             response.ehResult = pResponse->getResponseResult();
582             response.payload = (unsigned char*) payLoad.c_str();
583             response.payloadSize = payLoad.length() + 1;
584             response.persistentBufferFlag = 0;
585
586             response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
587             int i = 0;
588             for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
589             {
590                 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
591                 response.sendVendorSpecificHeaderOptions[i].optionID =
592                     static_cast<uint16_t>(it->getOptionID());
593                 response.sendVendorSpecificHeaderOptions[i].optionLength =
594                     (it->getOptionData()).length() + 1;
595                 memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
596                     (it->getOptionData()).c_str(),
597                     (it->getOptionData()).length() + 1);
598                 i++;
599             }
600
601             if(OC_EH_RESOURCE_CREATED == response.ehResult)
602             {
603                 std::string createdUri = pResponse->getNewResourceUri();
604                 strncpy(reinterpret_cast<char*>(response.resourceUri),
605                         createdUri.c_str(),
606                         createdUri.length() + 1);
607             }
608
609             if(cLock)
610             {
611                 std::lock_guard<std::recursive_mutex> lock(*cLock);
612                 result = OCDoResponse(&response);
613             }
614             else
615             {
616                 result = OC_STACK_ERROR;
617             }
618
619             if(result != OC_STACK_OK)
620             {
621                 oclog() << "Error sending response\n";
622             }
623             return result;
624         }
625     }
626
627     InProcServerWrapper::~InProcServerWrapper()
628     {
629         if(m_processThread.joinable())
630         {
631             m_threadRun = false;
632             m_processThread.join();
633         }
634
635         OCStop();
636     }
637 }