Merge remote-tracking branch 'origin/routing-manager'
[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             pRequest->setObservationInfo(observationInfo);
132         }
133     }
134 }
135
136 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
137                                                   OCEntityHandlerRequest * entityHandlerRequest,
138                                                   char* uri,
139                                                   void * /*callbackParam*/)
140 {
141     OCEntityHandlerResult result = OC_EH_ERROR;
142
143     OC::oclog() << "In Default device entity handler wrapper";
144
145     if(NULL == entityHandlerRequest)
146     {
147         oclog() << "Entity handler request is NULL.";
148         return OC_EH_ERROR;
149     }
150
151     auto pRequest = std::make_shared<OC::OCResourceRequest>();
152
153     formResourceRequest(flag, entityHandlerRequest, pRequest);
154
155     pRequest->setResourceUri(std::string(uri));
156
157     EntityHandler defHandler;
158     {
159         std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
160         defHandler = OC::details::defaultDeviceEntityHandler;
161     }
162
163     if(defHandler)
164     {
165         result = defHandler(pRequest);
166     }
167     else
168     {
169         oclog() << "Default device entity handler was not set.";
170         return OC_EH_ERROR;
171     }
172
173     return result;
174 }
175
176
177 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
178                                            OCEntityHandlerRequest * entityHandlerRequest,
179                                            void* /*callbackParam*/)
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 if (cfg.mode == ModeType::Gateway)
261         {
262             initType = OC_GATEWAY;
263         }
264         else
265         {
266             throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
267                                          OC_STACK_INVALID_PARAM);
268         }
269
270         OCTransportFlags serverFlags =
271                             static_cast<OCTransportFlags>(cfg.serverConnectivity & CT_MASK_FLAGS);
272         OCTransportFlags clientFlags =
273                             static_cast<OCTransportFlags>(cfg.clientConnectivity & CT_MASK_FLAGS);
274         OCStackResult result = OCInit1(initType, serverFlags, clientFlags);
275
276         if(OC_STACK_OK != result)
277         {
278             throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
279         }
280
281         m_threadRun = true;
282         m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
283     }
284
285     void InProcServerWrapper::processFunc()
286     {
287         auto cLock = m_csdkLock.lock();
288         while(cLock && m_threadRun)
289         {
290             OCStackResult result;
291
292             {
293                 std::lock_guard<std::recursive_mutex> lock(*cLock);
294                 result = OCProcess();
295             }
296
297             if(OC_STACK_ERROR == result)
298             {
299                 oclog() << "OCProcess failed with result " << result <<std::flush;
300                 // ...the value of variable result is simply ignored for now.
301             }
302
303             std::this_thread::sleep_for(std::chrono::milliseconds(10));
304         }
305     }
306
307     OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
308     {
309         auto cLock = m_csdkLock.lock();
310         OCStackResult result = OC_STACK_ERROR;
311         if(cLock)
312         {
313             std::lock_guard<std::recursive_mutex> lock(*cLock);
314             result = OCSetDeviceInfo(deviceInfo);
315         }
316         return result;
317     }
318
319      OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
320     {
321         auto cLock = m_csdkLock.lock();
322         OCStackResult result = OC_STACK_ERROR;
323         if(cLock)
324         {
325             std::lock_guard<std::recursive_mutex> lock(*cLock);
326             result = OCSetPlatformInfo(platformInfo);
327         }
328         return result;
329     }
330
331     OCStackResult InProcServerWrapper::registerResource(
332                     OCResourceHandle& resourceHandle,
333                     std::string& resourceURI,
334                     const std::string& resourceTypeName,
335                     const std::string& resourceInterface,
336                     EntityHandler& eHandler,
337                     uint8_t resourceProperties)
338
339     {
340         OCStackResult result = OC_STACK_ERROR;
341
342         auto cLock = m_csdkLock.lock();
343
344         if(cLock)
345         {
346             std::lock_guard<std::recursive_mutex> lock(*cLock);
347
348             if(NULL != eHandler)
349             {
350                 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
351                             resourceTypeName.c_str(), // const char * resourceTypeName
352                             resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
353                             resourceURI.c_str(), // const char * uri
354                             EntityHandlerWrapper, // OCEntityHandler entityHandler
355                             NULL,
356                             resourceProperties // uint8_t resourceProperties
357                             );
358             }
359             else
360             {
361                 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
362                             resourceTypeName.c_str(), // const char * resourceTypeName
363                             resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
364                             resourceURI.c_str(), // const char * uri
365                             NULL, // OCEntityHandler entityHandler
366                             NULL,
367                             resourceProperties // uint8_t resourceProperties
368                             );
369             }
370
371             if(result != OC_STACK_OK)
372             {
373                 resourceHandle = (OCResourceHandle) 0;
374             }
375             else
376             {
377                 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
378                 OC::details::entityHandlerMap[resourceHandle] = eHandler;
379                 OC::details::resourceUriMap[resourceHandle] = resourceURI;
380             }
381         }
382         else
383         {
384             result = OC_STACK_ERROR;
385         }
386
387         return result;
388     }
389
390
391
392     OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
393                                         (EntityHandler entityHandler)
394     {
395         OCStackResult result = OC_STACK_ERROR;
396
397         {
398             std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
399             OC::details::defaultDeviceEntityHandler = entityHandler;
400         }
401
402         if(entityHandler)
403         {
404             result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
405         }
406         else
407         {
408             // If Null passed we unset
409             result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
410         }
411
412         return result;
413     }
414
415     OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
416     {
417         auto cLock = m_csdkLock.lock();
418         OCStackResult result = OC_STACK_ERROR;
419
420         if(cLock)
421         {
422             std::lock_guard<std::recursive_mutex> lock(*cLock);
423             result = OCDeleteResource(resourceHandle);
424
425             if(result == OC_STACK_OK)
426             {
427                 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
428                 OC::details::resourceUriMap.erase(resourceHandle);
429             }
430             else
431             {
432                 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
433             }
434         }
435         else
436         {
437             result = OC_STACK_ERROR;
438         }
439
440         return result;
441     }
442
443     OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
444                      const std::string& resourceTypeName)
445     {
446         auto cLock = m_csdkLock.lock();
447         OCStackResult result;
448         if(cLock)
449         {
450             std::lock_guard<std::recursive_mutex> lock(*cLock);
451             result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
452         }
453         else
454         {
455             result = OC_STACK_ERROR;
456         }
457
458         if (result != OC_STACK_OK)
459         {
460             throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
461         }
462         return result;
463     }
464
465     OCStackResult InProcServerWrapper::bindInterfaceToResource(
466                      const OCResourceHandle& resourceHandle,
467                      const std::string& resourceInterfaceName)
468     {
469         auto cLock = m_csdkLock.lock();
470         OCStackResult result;
471         if(cLock)
472         {
473             std::lock_guard<std::recursive_mutex> lock(*cLock);
474             result = OCBindResourceInterfaceToResource(resourceHandle,
475                         resourceInterfaceName.c_str());
476         }
477         else
478         {
479             result = OC_STACK_ERROR;
480         }
481
482         if (result != OC_STACK_OK)
483         {
484             throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
485         }
486         return result;
487     }
488
489     OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
490     {
491         auto cLock = m_csdkLock.lock();
492         OCStackResult result = OC_STACK_ERROR;
493         if(cLock)
494         {
495             std::lock_guard<std::recursive_mutex> lock(*cLock);
496             result = OCStartPresence(seconds);
497         }
498
499         if(result != OC_STACK_OK)
500         {
501             throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
502         }
503         return result;
504     }
505
506     OCStackResult InProcServerWrapper::stopPresence()
507     {
508         auto cLock = m_csdkLock.lock();
509         OCStackResult result = OC_STACK_ERROR;
510         if(cLock)
511         {
512             std::lock_guard<std::recursive_mutex> lock(*cLock);
513             result = OCStopPresence();
514         }
515
516         if(result != OC_STACK_OK)
517         {
518             throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
519         }
520         return result;
521     }
522
523     OCStackResult InProcServerWrapper::sendResponse(
524         const std::shared_ptr<OCResourceResponse> pResponse)
525     {
526         auto cLock = m_csdkLock.lock();
527         OCStackResult result = OC_STACK_ERROR;
528
529         if(!pResponse)
530         {
531             result = OC_STACK_MALFORMED_RESPONSE;
532             throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
533         }
534         else
535         {
536             OCEntityHandlerResponse response;
537 //            OCRepPayload* payLoad = pResponse->getPayload();
538             HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
539
540             response.requestHandle = pResponse->getRequestHandle();
541             response.resourceHandle = pResponse->getResourceHandle();
542             response.ehResult = pResponse->getResponseResult();
543
544             response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
545
546             response.persistentBufferFlag = 0;
547
548             response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
549             int i = 0;
550             for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
551             {
552                 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
553                 response.sendVendorSpecificHeaderOptions[i].optionID =
554                     static_cast<uint16_t>(it->getOptionID());
555                 response.sendVendorSpecificHeaderOptions[i].optionLength =
556                     (it->getOptionData()).length() + 1;
557                 std::string optionData = it->getOptionData();
558                 std::copy(optionData.begin(),
559                          optionData.end(),
560                          response.sendVendorSpecificHeaderOptions[i].optionData);
561                 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
562                     = '\0';
563                 i++;
564             }
565
566             if(OC_EH_RESOURCE_CREATED == response.ehResult)
567             {
568                 pResponse->getNewResourceUri().copy(response.resourceUri,
569                         sizeof (response.resourceUri) - 1);
570                 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
571             }
572
573             if(cLock)
574             {
575                 std::lock_guard<std::recursive_mutex> lock(*cLock);
576                 result = OCDoResponse(&response);
577             }
578             else
579             {
580                 OICFree(response.payload);
581                 result = OC_STACK_ERROR;
582             }
583
584             if(result != OC_STACK_OK)
585             {
586                 oclog() << "Error sending response\n";
587             }
588             return result;
589         }
590     }
591
592     InProcServerWrapper::~InProcServerWrapper()
593     {
594         if(m_processThread.joinable())
595         {
596             m_threadRun = false;
597             m_processThread.join();
598         }
599
600         OCStop();
601     }
602 }
603