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