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