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>
35 #include <ocpayload.h>
38 #include <oic_malloc.h>
39 #include <OCPlatform.h>
40 #include <OCUtilities.h>
43 #include <rd_client.h>
53 std::mutex serverWrapperLock;
54 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
55 std::map <OCResourceHandle, std::string> resourceUriMap;
56 EntityHandler defaultDeviceEntityHandler;
60 void formResourceRequest(OCEntityHandlerFlag flag,
61 OCEntityHandlerRequest * entityHandlerRequest,
62 std::shared_ptr<OCResourceRequest> pRequest)
64 if(pRequest && entityHandlerRequest)
66 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
67 pRequest->setResourceHandle(entityHandlerRequest->resource);
68 pRequest->setMessageID(entityHandlerRequest->messageID);
71 if(flag & OC_REQUEST_FLAG)
73 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
75 if(entityHandlerRequest)
77 if(entityHandlerRequest->query)
79 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
80 entityHandlerRequest->query);
84 pRequest->setQueryParams(qp);
87 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
89 //Set the header options here.
91 std::string optionData;
92 HeaderOptions headerOptions;
95 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
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);
104 pRequest->setHeaderOptions(headerOptions);
107 if(OC_REST_GET == entityHandlerRequest->method)
109 pRequest->setRequestType(OC::PlatformCommands::GET);
111 else if(OC_REST_PUT == entityHandlerRequest->method)
113 pRequest->setRequestType(OC::PlatformCommands::PUT);
114 pRequest->setPayload(entityHandlerRequest->payload);
116 else if(OC_REST_POST == entityHandlerRequest->method)
118 pRequest->setRequestType(OC::PlatformCommands::POST);
119 pRequest->setPayload(entityHandlerRequest->payload);
121 else if(OC_REST_DELETE == entityHandlerRequest->method)
123 pRequest->setRequestType(OC::PlatformCommands::DELETE);
128 if(flag & OC_OBSERVE_FLAG)
130 pRequest->setRequestHandlerFlag(
131 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
133 if(entityHandlerRequest)
135 OC::ObservationInfo observationInfo;
136 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
137 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
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);
149 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
150 OCEntityHandlerRequest * entityHandlerRequest,
152 void * /*callbackParam*/)
154 OCEntityHandlerResult result = OC_EH_ERROR;
156 OC::oclog() << "In Default device entity handler wrapper";
158 if(NULL == entityHandlerRequest)
160 oclog() << "Entity handler request is NULL.";
164 auto pRequest = std::make_shared<OC::OCResourceRequest>();
166 formResourceRequest(flag, entityHandlerRequest, pRequest);
168 pRequest->setResourceUri(std::string(uri));
170 EntityHandler defHandler;
172 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
173 defHandler = OC::details::defaultDeviceEntityHandler;
178 result = defHandler(pRequest);
182 oclog() << "Default device entity handler was not set.";
190 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
191 OCEntityHandlerRequest * entityHandlerRequest,
192 void* /*callbackParam*/)
194 OCEntityHandlerResult result = OC_EH_ERROR;
196 oclog() << "\nIn entity handler wrapper: " << endl;
198 if(NULL == entityHandlerRequest)
200 oclog() << "Entity handler request is NULL." << endl;
204 auto pRequest = std::make_shared<OC::OCResourceRequest>();
206 formResourceRequest(flag, entityHandlerRequest, pRequest);
208 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
209 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
211 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
212 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
213 resourceUriEnd = OC::details::resourceUriMap.end();
215 // Finding the corresponding URI for a resource handle and set the URI in the request
216 if(resourceUriEntry != resourceUriEnd)
218 pRequest->setResourceUri(resourceUriEntry->second);
222 oclog() << "Resource handle not found; Resource URI not set in request";
226 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
227 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
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();
235 if(entityHandlerEntry != entityHandlerEnd)
237 // Call CPP Application Entity Handler
238 if(entityHandlerEntry->second)
240 result = entityHandlerEntry->second(pRequest);
244 oclog() << "C stack should not call again for parent resource\n";
250 oclog() << "No entity handler found." << endl;
259 InProcServerWrapper::InProcServerWrapper(
260 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
261 : m_csdkLock(csdkLock)
265 if(cfg.mode == ModeType::Server)
267 initType = OC_SERVER;
269 else if (cfg.mode == ModeType::Both)
271 initType = OC_CLIENT_SERVER;
273 else if (cfg.mode == ModeType::Gateway)
275 initType = OC_GATEWAY;
279 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
280 OC_STACK_INVALID_PARAM);
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);
289 if(OC_STACK_OK != result)
291 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
295 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
298 void InProcServerWrapper::processFunc()
300 auto cLock = m_csdkLock.lock();
301 while(cLock && m_threadRun)
303 OCStackResult result;
306 std::lock_guard<std::recursive_mutex> lock(*cLock);
307 result = OCProcess();
310 if(OC_STACK_ERROR == result)
312 oclog() << "OCProcess failed with result " << result <<std::flush;
313 // ...the value of variable result is simply ignored for now.
316 std::this_thread::sleep_for(std::chrono::milliseconds(10));
320 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
322 auto cLock = m_csdkLock.lock();
323 OCStackResult result = OC_STACK_ERROR;
326 std::lock_guard<std::recursive_mutex> lock(*cLock);
327 result = OCSetDeviceInfo(deviceInfo);
332 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
334 auto cLock = m_csdkLock.lock();
335 OCStackResult result = OC_STACK_ERROR;
338 std::lock_guard<std::recursive_mutex> lock(*cLock);
339 result = OCSetPlatformInfo(platformInfo);
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)
353 OCStackResult result = OC_STACK_ERROR;
355 auto cLock = m_csdkLock.lock();
359 std::lock_guard<std::recursive_mutex> lock(*cLock);
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
369 resourceProperties // uint8_t resourceProperties
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
380 resourceProperties // uint8_t resourceProperties
384 if(result != OC_STACK_OK)
386 resourceHandle = (OCResourceHandle) 0;
390 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
391 OC::details::entityHandlerMap[resourceHandle] = eHandler;
392 OC::details::resourceUriMap[resourceHandle] = resourceURI;
397 result = OC_STACK_ERROR;
405 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
406 (EntityHandler entityHandler)
408 OCStackResult result = OC_STACK_ERROR;
411 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
412 OC::details::defaultDeviceEntityHandler = entityHandler;
417 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
421 // If Null passed we unset
422 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
428 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
430 auto cLock = m_csdkLock.lock();
431 OCStackResult result = OC_STACK_ERROR;
435 std::lock_guard<std::recursive_mutex> lock(*cLock);
436 result = OCDeleteResource(resourceHandle);
438 if(result == OC_STACK_OK)
440 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
441 OC::details::resourceUriMap.erase(resourceHandle);
445 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
450 result = OC_STACK_ERROR;
456 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
457 const std::string& resourceTypeName)
459 auto cLock = m_csdkLock.lock();
460 OCStackResult result;
463 std::lock_guard<std::recursive_mutex> lock(*cLock);
464 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
468 result = OC_STACK_ERROR;
471 if (result != OC_STACK_OK)
473 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
478 OCStackResult InProcServerWrapper::bindInterfaceToResource(
479 const OCResourceHandle& resourceHandle,
480 const std::string& resourceInterfaceName)
482 auto cLock = m_csdkLock.lock();
483 OCStackResult result;
486 std::lock_guard<std::recursive_mutex> lock(*cLock);
487 result = OCBindResourceInterfaceToResource(resourceHandle,
488 resourceInterfaceName.c_str());
492 result = OC_STACK_ERROR;
495 if (result != OC_STACK_OK)
497 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
502 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
504 auto cLock = m_csdkLock.lock();
505 OCStackResult result = OC_STACK_ERROR;
508 std::lock_guard<std::recursive_mutex> lock(*cLock);
509 result = OCStartPresence(seconds);
512 if(result != OC_STACK_OK)
514 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
519 OCStackResult InProcServerWrapper::stopPresence()
521 auto cLock = m_csdkLock.lock();
522 OCStackResult result = OC_STACK_ERROR;
525 std::lock_guard<std::recursive_mutex> lock(*cLock);
526 result = OCStopPresence();
529 if(result != OC_STACK_OK)
531 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
536 OCStackResult InProcServerWrapper::sendResponse(
537 const std::shared_ptr<OCResourceResponse> pResponse)
539 auto cLock = m_csdkLock.lock();
540 OCStackResult result = OC_STACK_ERROR;
544 result = OC_STACK_MALFORMED_RESPONSE;
545 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
549 OCEntityHandlerResponse response;
550 // OCRepPayload* payLoad = pResponse->getPayload();
551 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
553 response.requestHandle = pResponse->getRequestHandle();
554 response.resourceHandle = pResponse->getResourceHandle();
555 response.ehResult = pResponse->getResponseResult();
557 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
559 response.persistentBufferFlag = 0;
561 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
563 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
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(),
573 response.sendVendorSpecificHeaderOptions[i].optionData);
574 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
579 if(OC_EH_RESOURCE_CREATED == response.ehResult)
581 pResponse->getNewResourceUri().copy(response.resourceUri,
582 sizeof (response.resourceUri) - 1);
583 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
588 std::lock_guard<std::recursive_mutex> lock(*cLock);
589 result = OCDoResponse(&response);
593 OICFree(response.payload);
594 result = OC_STACK_ERROR;
597 if(result != OC_STACK_OK)
599 oclog() << "Error sending response\n";
606 OCRepresentation parseRDResponseCallback(OCClientResponse* clientResponse)
608 if (nullptr == clientResponse || nullptr == clientResponse->payload ||
609 PAYLOAD_TYPE_REPRESENTATION != clientResponse->payload->type)
611 return OCRepresentation();
615 oc.setPayload(clientResponse->payload);
617 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
618 if (it == oc.representations().end())
620 return OCRepresentation();
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);
629 std::for_each(it, oc.representations().end(),
630 [&root](const OCRepresentation& repItr)
631 {root.addChild(repItr);});
636 OCStackApplicationResult publishResourceToRDCallback(void* ctx, OCDoHandle /*handle*/,
637 OCClientResponse* clientResponse)
639 ServerCallbackContext::PublishContext* context =
640 static_cast<ServerCallbackContext::PublishContext*>(ctx);
644 // Update resource unique id in stack.
647 if (clientResponse->payload)
649 OCRepPayload *rdPayload = (OCRepPayload *) clientResponse->payload;
650 OCRepPayload **links = NULL;
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++)
657 OCRepPayloadGetPropString(links[i], OC_RSRVD_HREF, &uri);
658 OCResourceHandle handle = OCGetResourceHandleAtUri(uri);
660 OCRepPayloadGetPropInt(links[i], OC_RSRVD_INS, &ins);
661 OCBindResourceInsToResource(handle, ins);
664 OCRepresentation rep = parseRDResponseCallback(clientResponse);
665 std::thread exec(context->callback, rep, clientResponse->result);
669 catch (OC::OCException& e)
671 oclog() <<"Exception in publishResourceToRDCallback, ignoring response: "
672 <<e.what() <<std::flush;
675 return OC_STACK_KEEP_TRANSACTION;
678 OCStackResult InProcServerWrapper::publishResourceToRD(const std::string& host,
679 OCConnectivityType connectivityType,
680 ResourceHandles& resourceHandles,
681 PublishResourceCallback& callback,
682 OCQualityOfService qos)
684 ServerCallbackContext::PublishContext* ctx =
685 new ServerCallbackContext::PublishContext(callback);
686 OCCallbackData cbdata(
687 static_cast<void*>(ctx),
688 publishResourceToRDCallback,
690 {delete static_cast<ServerCallbackContext::PublishContext*>(c);}
693 auto cLock = m_csdkLock.lock();
694 OCStackResult result = OC_STACK_ERROR;
697 std::lock_guard<std::recursive_mutex> lock(*cLock);
698 result = OCRDPublish(host.c_str(), connectivityType, &resourceHandles[0],
699 resourceHandles.size(), &cbdata, qos);
702 if (OC_STACK_OK != result)
704 throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result);
709 OCStackApplicationResult deleteResourceFromRDCallback(void* ctx, OCDoHandle /*handle*/,
710 OCClientResponse* clientResponse)
712 ServerCallbackContext::DeleteContext* context =
713 static_cast<ServerCallbackContext::DeleteContext*>(ctx);
715 std::thread exec(context->callback, clientResponse->result);
717 return OC_STACK_DELETE_TRANSACTION;
720 OCStackResult InProcServerWrapper::deleteResourceFromRD(const std::string& host,
721 OCConnectivityType connectivityType,
722 ResourceHandles& resourceHandles,
723 DeleteResourceCallback& callback,
724 OCQualityOfService qos)
726 ServerCallbackContext::DeleteContext* ctx =
727 new ServerCallbackContext::DeleteContext(callback);
728 OCCallbackData cbdata(
729 static_cast<void*>(ctx),
730 deleteResourceFromRDCallback,
732 {delete static_cast<ServerCallbackContext::DeleteContext*>(c);}
735 auto cLock = m_csdkLock.lock();
736 OCStackResult result = OC_STACK_ERROR;
739 std::lock_guard<std::recursive_mutex> lock(*cLock);
740 result = OCRDDelete(host.c_str(), connectivityType, &resourceHandles[0],
741 resourceHandles.size(), &cbdata, qos);
744 if (OC_STACK_OK != result)
746 throw OCException(OC::Exception::PUBLISH_RESOURCE_FAILED, result);
752 InProcServerWrapper::~InProcServerWrapper()
754 if(m_processThread.joinable())
757 m_processThread.join();