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