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