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