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