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