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 #define TAG "OIC_SERVER_WRAPPER"
52 std::mutex serverWrapperLock;
53 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
54 std::map <OCResourceHandle, std::string> resourceUriMap;
55 EntityHandler defaultDeviceEntityHandler;
59 void formResourceRequest(OCEntityHandlerFlag flag,
60 OCEntityHandlerRequest * entityHandlerRequest,
61 std::shared_ptr<OCResourceRequest> pRequest)
63 if(pRequest && entityHandlerRequest)
65 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
66 pRequest->setResourceHandle(entityHandlerRequest->resource);
67 pRequest->setMessageID(entityHandlerRequest->messageID);
70 if(flag & OC_REQUEST_FLAG)
72 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
74 if(entityHandlerRequest)
76 if(entityHandlerRequest->query)
78 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
79 entityHandlerRequest->query);
83 pRequest->setQueryParams(qp);
86 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
88 //Set the header options here.
90 std::string optionData;
91 HeaderOptions headerOptions;
94 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
97 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
98 optionData = reinterpret_cast<const char*>
99 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
100 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
101 headerOptions.push_back(headerOption);
103 pRequest->setHeaderOptions(headerOptions);
106 if(OC_REST_GET == entityHandlerRequest->method)
108 pRequest->setRequestType(OC::PlatformCommands::GET);
110 else if(OC_REST_PUT == entityHandlerRequest->method)
112 pRequest->setRequestType(OC::PlatformCommands::PUT);
113 pRequest->setPayload(entityHandlerRequest->payload);
115 else if(OC_REST_POST == entityHandlerRequest->method)
117 pRequest->setRequestType(OC::PlatformCommands::POST);
118 pRequest->setPayload(entityHandlerRequest->payload);
120 else if(OC_REST_DELETE == entityHandlerRequest->method)
122 pRequest->setRequestType(OC::PlatformCommands::DELETE);
127 if(flag & OC_OBSERVE_FLAG)
129 pRequest->setRequestHandlerFlag(
130 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
132 if(entityHandlerRequest)
134 OC::ObservationInfo observationInfo;
135 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
136 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
138 observationInfo.connectivityType = static_cast<OCConnectivityType>(
139 (entityHandlerRequest->devAddr.adapter << CT_ADAPTER_SHIFT) |
140 (entityHandlerRequest->devAddr.flags & CT_MASK_FLAGS));
141 observationInfo.address = entityHandlerRequest->devAddr.addr;
142 observationInfo.port = entityHandlerRequest->devAddr.port;
143 pRequest->setObservationInfo(observationInfo);
148 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
149 OCEntityHandlerRequest * entityHandlerRequest,
151 void * /*callbackParam*/)
153 OCEntityHandlerResult result = OC_EH_ERROR;
155 OC::oclog() << "In Default device entity handler wrapper";
157 if(NULL == entityHandlerRequest)
159 oclog() << "Entity handler request is NULL.";
163 auto pRequest = std::make_shared<OC::OCResourceRequest>();
165 formResourceRequest(flag, entityHandlerRequest, pRequest);
167 pRequest->setResourceUri(std::string(uri));
169 EntityHandler defHandler;
171 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
172 defHandler = OC::details::defaultDeviceEntityHandler;
177 result = defHandler(pRequest);
181 oclog() << "Default device entity handler was not set.";
189 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
190 OCEntityHandlerRequest * entityHandlerRequest,
191 void* /*callbackParam*/)
193 OCEntityHandlerResult result = OC_EH_ERROR;
195 oclog() << "\nIn entity handler wrapper: " << endl;
197 if(NULL == entityHandlerRequest)
199 oclog() << "Entity handler request is NULL." << endl;
203 auto pRequest = std::make_shared<OC::OCResourceRequest>();
205 formResourceRequest(flag, entityHandlerRequest, pRequest);
207 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
208 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
210 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
211 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
212 resourceUriEnd = OC::details::resourceUriMap.end();
214 // Finding the corresponding URI for a resource handle and set the URI in the request
215 if(resourceUriEntry != resourceUriEnd)
217 pRequest->setResourceUri(resourceUriEntry->second);
221 oclog() << "Resource handle not found; Resource URI not set in request";
225 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
226 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
228 // Finding the corresponding CPP Application entityHandler for a given resource
229 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
230 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
231 entityHandlerEnd = OC::details::entityHandlerMap.end();
234 if(entityHandlerEntry != entityHandlerEnd)
236 // Call CPP Application Entity Handler
237 if(entityHandlerEntry->second)
239 result = entityHandlerEntry->second(pRequest);
243 oclog() << "C stack should not call again for parent resource\n";
249 oclog() << "No entity handler found." << endl;
258 InProcServerWrapper::InProcServerWrapper(
259 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
260 : m_threadRun(false),
261 m_csdkLock(csdkLock),
267 OCStackResult InProcServerWrapper::start()
269 OIC_LOG_V(INFO, TAG, "start ocplatform for server : %d", m_cfg.transportType);
272 if(m_cfg.mode == ModeType::Server)
274 initType = OC_SERVER;
276 else if (m_cfg.mode == ModeType::Both)
278 initType = OC_CLIENT_SERVER;
280 else if (m_cfg.mode == ModeType::Gateway)
282 initType = OC_GATEWAY;
286 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
287 OC_STACK_INVALID_PARAM);
290 OCTransportFlags serverFlags =
291 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
292 OCTransportFlags clientFlags =
293 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
294 OCStackResult result = OCInit2(initType, serverFlags, clientFlags,
295 m_cfg.transportType);
297 if(OC_STACK_OK != result)
299 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
302 if (false == m_threadRun)
305 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
310 OCStackResult InProcServerWrapper::stop()
312 OIC_LOG(INFO, TAG, "stop");
314 if(m_processThread.joinable())
317 m_processThread.join();
320 OCStackResult res = OCStop();
322 if (OC_STACK_OK != res)
324 throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, res);
330 void InProcServerWrapper::processFunc()
332 auto cLock = m_csdkLock.lock();
333 while(cLock && m_threadRun)
335 OCStackResult result;
338 std::lock_guard<std::recursive_mutex> lock(*cLock);
339 result = OCProcess();
342 if(OC_STACK_ERROR == result)
344 oclog() << "OCProcess failed with result " << result <<std::flush;
345 // ...the value of variable result is simply ignored for now.
348 std::this_thread::sleep_for(std::chrono::milliseconds(10));
352 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
354 auto cLock = m_csdkLock.lock();
355 OCStackResult result = OC_STACK_ERROR;
358 std::lock_guard<std::recursive_mutex> lock(*cLock);
359 result = OCSetDeviceInfo(deviceInfo);
364 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
366 auto cLock = m_csdkLock.lock();
367 OCStackResult result = OC_STACK_ERROR;
370 std::lock_guard<std::recursive_mutex> lock(*cLock);
371 result = OCSetPlatformInfo(platformInfo);
376 OCStackResult InProcServerWrapper::setPropertyValue(OCPayloadType type, const std::string& propName,
377 const std::string& propValue)
379 auto cLock = m_csdkLock.lock();
380 OCStackResult result = OC_STACK_ERROR;
383 std::lock_guard<std::recursive_mutex> lock(*cLock);
384 result = OCSetPropertyValue(type, propName.c_str(), (void *)propValue.c_str());
389 OCStackResult InProcServerWrapper::getPropertyValue(OCPayloadType type, const std::string& propName,
390 std::string& propValue)
392 auto cLock = m_csdkLock.lock();
393 OCStackResult result = OC_STACK_ERROR;
396 std::lock_guard<std::recursive_mutex> lock(*cLock);
397 result = OCGetPropertyValue(type, propName.c_str(), (void **)propValue.c_str());
402 OCStackResult InProcServerWrapper::registerResource(
403 OCResourceHandle& resourceHandle,
404 std::string& resourceURI,
405 const std::string& resourceTypeName,
406 const std::string& resourceInterface,
407 EntityHandler& eHandler,
408 uint8_t resourceProperties)
411 OCStackResult result = OC_STACK_ERROR;
413 auto cLock = m_csdkLock.lock();
417 std::lock_guard<std::recursive_mutex> lock(*cLock);
421 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
422 resourceTypeName.c_str(), // const char * resourceTypeName
423 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
424 resourceURI.c_str(), // const char * uri
425 EntityHandlerWrapper, // OCEntityHandler entityHandler
427 resourceProperties // uint8_t resourceProperties
432 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
433 resourceTypeName.c_str(), // const char * resourceTypeName
434 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
435 resourceURI.c_str(), // const char * uri
436 NULL, // OCEntityHandler entityHandler
438 resourceProperties // uint8_t resourceProperties
442 if(result != OC_STACK_OK)
444 resourceHandle = (OCResourceHandle) 0;
448 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
449 OC::details::entityHandlerMap[resourceHandle] = eHandler;
450 OC::details::resourceUriMap[resourceHandle] = resourceURI;
455 result = OC_STACK_ERROR;
463 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
464 (EntityHandler entityHandler)
466 OCStackResult result = OC_STACK_ERROR;
469 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
470 OC::details::defaultDeviceEntityHandler = entityHandler;
475 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
479 // If Null passed we unset
480 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
486 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
488 auto cLock = m_csdkLock.lock();
489 OCStackResult result = OC_STACK_ERROR;
493 std::lock_guard<std::recursive_mutex> lock(*cLock);
494 result = OCDeleteResource(resourceHandle);
496 if(result == OC_STACK_OK)
498 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
499 OC::details::resourceUriMap.erase(resourceHandle);
503 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
508 result = OC_STACK_ERROR;
514 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
515 const std::string& resourceTypeName)
517 auto cLock = m_csdkLock.lock();
518 OCStackResult result;
521 std::lock_guard<std::recursive_mutex> lock(*cLock);
522 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
526 result = OC_STACK_ERROR;
529 if (result != OC_STACK_OK)
531 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
536 OCStackResult InProcServerWrapper::bindInterfaceToResource(
537 const OCResourceHandle& resourceHandle,
538 const std::string& resourceInterfaceName)
540 auto cLock = m_csdkLock.lock();
541 OCStackResult result;
544 std::lock_guard<std::recursive_mutex> lock(*cLock);
545 result = OCBindResourceInterfaceToResource(resourceHandle,
546 resourceInterfaceName.c_str());
550 result = OC_STACK_ERROR;
553 if (result != OC_STACK_OK)
555 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
560 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
562 auto cLock = m_csdkLock.lock();
563 OCStackResult result = OC_STACK_ERROR;
566 std::lock_guard<std::recursive_mutex> lock(*cLock);
567 result = OCStartPresence(seconds);
570 if(result != OC_STACK_OK)
572 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
577 OCStackResult InProcServerWrapper::stopPresence()
579 auto cLock = m_csdkLock.lock();
580 OCStackResult result = OC_STACK_ERROR;
583 std::lock_guard<std::recursive_mutex> lock(*cLock);
584 result = OCStopPresence();
587 if(result != OC_STACK_OK)
589 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
594 OCStackResult InProcServerWrapper::sendResponse(
595 const std::shared_ptr<OCResourceResponse> pResponse)
597 auto cLock = m_csdkLock.lock();
598 OCStackResult result = OC_STACK_ERROR;
602 result = OC_STACK_MALFORMED_RESPONSE;
603 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
607 OCEntityHandlerResponse response;
608 // OCRepPayload* payLoad = pResponse->getPayload();
609 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
611 response.requestHandle = pResponse->getRequestHandle();
612 response.resourceHandle = pResponse->getResourceHandle();
613 response.ehResult = pResponse->getResponseResult();
615 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
617 response.persistentBufferFlag = 0;
619 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
621 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
623 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
624 response.sendVendorSpecificHeaderOptions[i].optionID =
625 static_cast<uint16_t>(it->getOptionID());
626 response.sendVendorSpecificHeaderOptions[i].optionLength =
627 (it->getOptionData()).length() + 1;
628 std::string optionData = it->getOptionData();
629 std::copy(optionData.begin(),
631 response.sendVendorSpecificHeaderOptions[i].optionData);
632 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
637 if(OC_EH_RESOURCE_CREATED == response.ehResult)
639 pResponse->getNewResourceUri().copy(response.resourceUri,
640 sizeof (response.resourceUri) - 1);
641 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
646 std::lock_guard<std::recursive_mutex> lock(*cLock);
647 result = OCDoResponse(&response);
651 result = OC_STACK_ERROR;
654 if(result != OC_STACK_OK)
656 oclog() << "Error sending response\n";
659 OCPayloadDestroy(response.payload);
664 OCStackResult InProcServerWrapper::notifyAllObservers(OCResourceHandle resourceHandle,
665 QualityOfService QoS)
667 auto cLock = m_csdkLock.lock();
668 OCStackResult result = OC_STACK_ERROR;
671 std::lock_guard<std::recursive_mutex> lock(*cLock);
672 result = OCNotifyAllObservers(resourceHandle, static_cast<OCQualityOfService>(QoS));
678 OCStackResult InProcServerWrapper::notifyListOfObservers(OCResourceHandle resourceHandle,
679 ObservationIds& observationIds,
680 const std::shared_ptr<OCResourceResponse> pResponse,
681 QualityOfService QoS)
685 return OC_STACK_ERROR;
688 auto cLock = m_csdkLock.lock();
689 OCStackResult result = OC_STACK_ERROR;
692 std::lock_guard<std::recursive_mutex> lock(*cLock);
694 OCRepPayload* pl = pResponse->getResourceRepresentation().getPayload();
695 result = OCNotifyListOfObservers(resourceHandle,
697 observationIds.size(),
699 static_cast<OCQualityOfService>(QoS));
700 OCRepPayloadDestroy(pl);
703 if (result != OC_STACK_OK)
705 throw OCException(OC::Exception::NOTIFY_LIST_OBSERVERS_FAILED, result);
710 InProcServerWrapper::~InProcServerWrapper()
716 catch (InitializeException &e)
718 oclog() << "Exception in stop"<< e.what() << std::flush;