1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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
11 // http://www.apache.org/licenses/LICENSE-2.0
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.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30 #include <InProcServerWrapper.h>
31 #include <InitializeException.h>
32 #include <OCResourceRequest.h>
33 #include <OCResourceResponse.h>
36 #include <oic_malloc.h>
37 #include <OCPlatform.h>
38 #include <OCUtilities.h>
41 #include <oicresourcedirectory.h>
51 std::mutex serverWrapperLock;
52 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
53 std::map <OCResourceHandle, std::string> resourceUriMap;
54 EntityHandler defaultDeviceEntityHandler;
58 void formResourceRequest(OCEntityHandlerFlag flag,
59 OCEntityHandlerRequest * entityHandlerRequest,
60 std::shared_ptr<OCResourceRequest> pRequest)
62 if(pRequest && entityHandlerRequest)
64 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
65 pRequest->setResourceHandle(entityHandlerRequest->resource);
66 pRequest->setMessageID(entityHandlerRequest->messageID);
69 if(flag & OC_REQUEST_FLAG)
71 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
73 if(entityHandlerRequest)
75 if(entityHandlerRequest->query)
77 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
78 entityHandlerRequest->query);
82 pRequest->setQueryParams(qp);
85 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
87 //Set the header options here.
89 std::string optionData;
90 HeaderOptions headerOptions;
93 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
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);
102 pRequest->setHeaderOptions(headerOptions);
105 if(OC_REST_GET == entityHandlerRequest->method)
107 pRequest->setRequestType(OC::PlatformCommands::GET);
109 else if(OC_REST_PUT == entityHandlerRequest->method)
111 pRequest->setRequestType(OC::PlatformCommands::PUT);
112 pRequest->setPayload(entityHandlerRequest->payload);
114 else if(OC_REST_POST == entityHandlerRequest->method)
116 pRequest->setRequestType(OC::PlatformCommands::POST);
117 pRequest->setPayload(entityHandlerRequest->payload);
119 else if(OC_REST_DELETE == entityHandlerRequest->method)
121 pRequest->setRequestType(OC::PlatformCommands::DELETE);
126 if(flag & OC_OBSERVE_FLAG)
128 pRequest->setRequestHandlerFlag(
129 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
131 if(entityHandlerRequest)
133 OC::ObservationInfo observationInfo;
134 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
135 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
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);
147 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
148 OCEntityHandlerRequest * entityHandlerRequest,
150 void * /*callbackParam*/)
152 OCEntityHandlerResult result = OC_EH_ERROR;
154 OC::oclog() << "In Default device entity handler wrapper";
156 if(NULL == entityHandlerRequest)
158 oclog() << "Entity handler request is NULL.";
162 auto pRequest = std::make_shared<OC::OCResourceRequest>();
164 formResourceRequest(flag, entityHandlerRequest, pRequest);
166 pRequest->setResourceUri(std::string(uri));
168 EntityHandler defHandler;
170 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
171 defHandler = OC::details::defaultDeviceEntityHandler;
176 result = defHandler(pRequest);
180 oclog() << "Default device entity handler was not set.";
188 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
189 OCEntityHandlerRequest * entityHandlerRequest,
190 void* /*callbackParam*/)
192 OCEntityHandlerResult result = OC_EH_ERROR;
194 oclog() << "\nIn entity handler wrapper: " << endl;
196 if(NULL == entityHandlerRequest)
198 oclog() << "Entity handler request is NULL." << endl;
202 auto pRequest = std::make_shared<OC::OCResourceRequest>();
204 formResourceRequest(flag, entityHandlerRequest, pRequest);
206 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
207 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
209 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
210 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
211 resourceUriEnd = OC::details::resourceUriMap.end();
213 // Finding the corresponding URI for a resource handle and set the URI in the request
214 if(resourceUriEntry != resourceUriEnd)
216 pRequest->setResourceUri(resourceUriEntry->second);
220 oclog() << "Resource handle not found; Resource URI not set in request";
224 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
225 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
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();
233 if(entityHandlerEntry != entityHandlerEnd)
235 // Call CPP Application Entity Handler
236 if(entityHandlerEntry->second)
238 result = entityHandlerEntry->second(pRequest);
242 oclog() << "C stack should not call again for parent resource\n";
248 oclog() << "No entity handler found." << endl;
257 InProcServerWrapper::InProcServerWrapper(
258 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
259 : m_csdkLock(csdkLock)
263 if(cfg.mode == ModeType::Server)
265 initType = OC_SERVER;
267 else if (cfg.mode == ModeType::Both)
269 initType = OC_CLIENT_SERVER;
271 else if (cfg.mode == ModeType::Gateway)
273 initType = OC_GATEWAY;
277 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
278 OC_STACK_INVALID_PARAM);
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);
287 if(OC_STACK_OK != result)
289 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
293 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
296 void InProcServerWrapper::processFunc()
298 auto cLock = m_csdkLock.lock();
299 while(cLock && m_threadRun)
301 OCStackResult result;
304 std::lock_guard<std::recursive_mutex> lock(*cLock);
305 result = OCProcess();
308 if(OC_STACK_ERROR == result)
310 oclog() << "OCProcess failed with result " << result <<std::flush;
311 // ...the value of variable result is simply ignored for now.
314 std::this_thread::sleep_for(std::chrono::milliseconds(10));
318 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
320 auto cLock = m_csdkLock.lock();
321 OCStackResult result = OC_STACK_ERROR;
324 std::lock_guard<std::recursive_mutex> lock(*cLock);
325 result = OCSetDeviceInfo(deviceInfo);
330 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
332 auto cLock = m_csdkLock.lock();
333 OCStackResult result = OC_STACK_ERROR;
336 std::lock_guard<std::recursive_mutex> lock(*cLock);
337 result = OCSetPlatformInfo(platformInfo);
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)
351 OCStackResult result = OC_STACK_ERROR;
353 auto cLock = m_csdkLock.lock();
357 std::lock_guard<std::recursive_mutex> lock(*cLock);
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
367 resourceProperties // uint8_t resourceProperties
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
378 resourceProperties // uint8_t resourceProperties
382 if(result != OC_STACK_OK)
384 resourceHandle = (OCResourceHandle) 0;
388 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
389 OC::details::entityHandlerMap[resourceHandle] = eHandler;
390 OC::details::resourceUriMap[resourceHandle] = resourceURI;
395 result = OC_STACK_ERROR;
403 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
404 (EntityHandler entityHandler)
406 OCStackResult result = OC_STACK_ERROR;
409 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
410 OC::details::defaultDeviceEntityHandler = entityHandler;
415 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
419 // If Null passed we unset
420 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
426 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
428 auto cLock = m_csdkLock.lock();
429 OCStackResult result = OC_STACK_ERROR;
433 std::lock_guard<std::recursive_mutex> lock(*cLock);
434 result = OCDeleteResource(resourceHandle);
436 if(result == OC_STACK_OK)
438 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
439 OC::details::resourceUriMap.erase(resourceHandle);
443 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
448 result = OC_STACK_ERROR;
454 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
455 const std::string& resourceTypeName)
457 auto cLock = m_csdkLock.lock();
458 OCStackResult result;
461 std::lock_guard<std::recursive_mutex> lock(*cLock);
462 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
466 result = OC_STACK_ERROR;
469 if (result != OC_STACK_OK)
471 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
476 OCStackResult InProcServerWrapper::bindInterfaceToResource(
477 const OCResourceHandle& resourceHandle,
478 const std::string& resourceInterfaceName)
480 auto cLock = m_csdkLock.lock();
481 OCStackResult result;
484 std::lock_guard<std::recursive_mutex> lock(*cLock);
485 result = OCBindResourceInterfaceToResource(resourceHandle,
486 resourceInterfaceName.c_str());
490 result = OC_STACK_ERROR;
493 if (result != OC_STACK_OK)
495 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
500 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
502 auto cLock = m_csdkLock.lock();
503 OCStackResult result = OC_STACK_ERROR;
506 std::lock_guard<std::recursive_mutex> lock(*cLock);
507 result = OCStartPresence(seconds);
510 if(result != OC_STACK_OK)
512 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
517 OCStackResult InProcServerWrapper::stopPresence()
519 auto cLock = m_csdkLock.lock();
520 OCStackResult result = OC_STACK_ERROR;
523 std::lock_guard<std::recursive_mutex> lock(*cLock);
524 result = OCStopPresence();
527 if(result != OC_STACK_OK)
529 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
534 OCStackResult InProcServerWrapper::sendResponse(
535 const std::shared_ptr<OCResourceResponse> pResponse)
537 auto cLock = m_csdkLock.lock();
538 OCStackResult result = OC_STACK_ERROR;
542 result = OC_STACK_MALFORMED_RESPONSE;
543 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
547 OCEntityHandlerResponse response;
548 // OCRepPayload* payLoad = pResponse->getPayload();
549 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
551 response.requestHandle = pResponse->getRequestHandle();
552 response.resourceHandle = pResponse->getResourceHandle();
553 response.ehResult = pResponse->getResponseResult();
555 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
557 response.persistentBufferFlag = 0;
559 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
561 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
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(),
571 response.sendVendorSpecificHeaderOptions[i].optionData);
572 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
577 if(OC_EH_RESOURCE_CREATED == response.ehResult)
579 pResponse->getNewResourceUri().copy(response.resourceUri,
580 sizeof (response.resourceUri) - 1);
581 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
586 std::lock_guard<std::recursive_mutex> lock(*cLock);
587 result = OCDoResponse(&response);
591 OICFree(response.payload);
592 result = OC_STACK_ERROR;
595 if(result != OC_STACK_OK)
597 oclog() << "Error sending response\n";
603 OCRepresentation parseRDResponseCallback(OCClientResponse* clientResponse)
605 if (nullptr == clientResponse || nullptr == clientResponse->payload ||
606 PAYLOAD_TYPE_RD != clientResponse->payload->type)
608 return OCRepresentation();
612 oc.setPayload(clientResponse->payload);
614 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
615 if (it == oc.representations().end())
617 return OCRepresentation();
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);
626 std::for_each(it, oc.representations().end(),
627 [&root](const OCRepresentation& repItr)
628 {root.addChild(repItr);});
633 OCStackApplicationResult publishResourceToRDCallback(void* ctx, OCDoHandle /*handle*/,
634 OCClientResponse* clientResponse)
636 ServerCallbackContext::PublishContext* context =
637 static_cast<ServerCallbackContext::PublishContext*>(ctx);
641 // Update resource unique id in stack.
644 if (clientResponse->payload)
646 OCRDPayload *rdPayload = (OCRDPayload *) clientResponse->payload;
647 OCLinksPayload *links = rdPayload->rdPublish->setLinks;
651 OCResourceHandle handle = OCGetResourceHandleAtUri(links->href);
652 OCBindResourceInsToResource(handle, links->ins);
659 OCRepresentation rep = parseRDResponseCallback(clientResponse);
660 std::thread exec(context->callback, rep, clientResponse->result);
663 catch (OC::OCException& e)
665 oclog() <<"Exception in publishResourceToRDCallback, ignoring response: "
666 <<e.what() <<std::flush;
669 return OC_STACK_KEEP_TRANSACTION;
672 OCStackResult InProcServerWrapper::publishResourceToRD(const std::string& host,
673 OCConnectivityType connectivityType,
674 ResourceHandles& resourceHandles,
675 PublishResourceCallback& callback,
676 OCQualityOfService qos)
678 ServerCallbackContext::PublishContext* ctx =
679 new ServerCallbackContext::PublishContext(callback);
680 OCCallbackData cbdata(
681 static_cast<void*>(ctx),
682 publishResourceToRDCallback,
684 {delete static_cast<ServerCallbackContext::PublishContext*>(c);}
687 auto cLock = m_csdkLock.lock();
688 OCStackResult result = OC_STACK_ERROR;
691 std::lock_guard<std::recursive_mutex> lock(*cLock);
692 result = OCRDPublish(host.c_str(), connectivityType, &resourceHandles[0],
693 resourceHandles.size(), &cbdata, qos);
696 if (OC_STACK_OK != result)
698 throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result);
703 OCStackApplicationResult deleteResourceFromRDCallback(void* ctx, OCDoHandle /*handle*/,
704 OCClientResponse* clientResponse)
706 ServerCallbackContext::DeleteContext* context =
707 static_cast<ServerCallbackContext::DeleteContext*>(ctx);
709 std::thread exec(context->callback, clientResponse->result);
711 return OC_STACK_DELETE_TRANSACTION;
714 OCStackResult InProcServerWrapper::deleteResourceFromRD(const std::string& host,
715 OCConnectivityType connectivityType,
716 ResourceHandles& resourceHandles,
717 DeleteResourceCallback& callback,
718 OCQualityOfService qos)
720 ServerCallbackContext::DeleteContext* ctx =
721 new ServerCallbackContext::DeleteContext(callback);
722 OCCallbackData cbdata(
723 static_cast<void*>(ctx),
724 deleteResourceFromRDCallback,
726 {delete static_cast<ServerCallbackContext::DeleteContext*>(c);}
729 auto cLock = m_csdkLock.lock();
730 OCStackResult result = OC_STACK_ERROR;
733 std::lock_guard<std::recursive_mutex> lock(*cLock);
734 result = OCRDDelete(host.c_str(), connectivityType, &resourceHandles[0],
735 resourceHandles.size(), &cbdata, qos);
738 if (OC_STACK_OK != result)
740 throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result);
745 InProcServerWrapper::~InProcServerWrapper()
747 if(m_processThread.joinable())
750 m_processThread.join();