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