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