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 char optionData[MAX_HEADER_OPTION_DATA_LENGTH + 1];
91 HeaderOptions headerOptions;
93 optionData[MAX_HEADER_OPTION_DATA_LENGTH] = '\0';
95 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
98 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
99 memcpy(optionData, entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData,
100 MAX_HEADER_OPTION_DATA_LENGTH);
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_threadRun(false),
262 m_csdkLock(csdkLock),
268 OCStackResult InProcServerWrapper::start()
270 OIC_LOG_V(INFO, TAG, "start ocplatform for server : %d", m_cfg.transportType);
273 if(m_cfg.mode == ModeType::Server)
275 initType = OC_SERVER;
277 else if (m_cfg.mode == ModeType::Both)
279 initType = OC_CLIENT_SERVER;
281 else if (m_cfg.mode == ModeType::Gateway)
283 initType = OC_GATEWAY;
287 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
288 OC_STACK_INVALID_PARAM);
291 OCTransportFlags serverFlags =
292 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
293 OCTransportFlags clientFlags =
294 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
295 OCStackResult result = OCInit2(initType, serverFlags, clientFlags,
296 m_cfg.transportType);
298 if(OC_STACK_OK != result)
300 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
303 if (false == m_threadRun)
306 #ifdef WITH_PROCESS_EVENT
307 m_processEvent = oc_event_new();
310 OIC_LOG(INFO, TAG, "oc_event_new failed!");
311 return OC_STACK_ERROR;
313 OCRegisterProcessEvent(m_processEvent);
315 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
320 OCStackResult InProcServerWrapper::stop()
322 OIC_LOG(INFO, TAG, "stop");
324 if(m_processThread.joinable())
327 #ifdef WITH_PROCESS_EVENT
330 oc_event_signal(m_processEvent);
333 m_processThread.join();
336 #ifdef WITH_PROCESS_EVENT
339 oc_event_free(m_processEvent);
340 m_processEvent = NULL;
344 OCStackResult res = OCStop();
346 if (OC_STACK_OK != res)
348 throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, res);
354 void InProcServerWrapper::processFunc()
356 #ifdef WITH_PROCESS_EVENT
357 uint32_t nextEventTime;
359 auto cLock = m_csdkLock.lock();
360 while(cLock && m_threadRun)
362 OCStackResult result;
365 std::lock_guard<std::recursive_mutex> lock(*cLock);
366 #ifdef WITH_PROCESS_EVENT
367 result = OCProcessEvent(&nextEventTime);
369 result = OCProcess();
373 if(OC_STACK_ERROR == result)
375 oclog() << "OCProcess failed with result " << result <<std::flush;
376 // ...the value of variable result is simply ignored for now.
379 #ifdef WITH_PROCESS_EVENT
380 oc_event_wait_for(m_processEvent, nextEventTime);
382 std::this_thread::sleep_for(std::chrono::milliseconds(10));
387 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
389 auto cLock = m_csdkLock.lock();
390 OCStackResult result = OC_STACK_ERROR;
393 std::lock_guard<std::recursive_mutex> lock(*cLock);
394 result = OCSetDeviceInfo(deviceInfo);
399 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
401 auto cLock = m_csdkLock.lock();
402 OCStackResult result = OC_STACK_ERROR;
405 std::lock_guard<std::recursive_mutex> lock(*cLock);
406 result = OCSetPlatformInfo(platformInfo);
411 OCStackResult InProcServerWrapper::setPropertyValue(OCPayloadType type, const std::string& propName,
412 const std::string& propValue)
414 auto cLock = m_csdkLock.lock();
415 OCStackResult result = OC_STACK_ERROR;
418 std::lock_guard<std::recursive_mutex> lock(*cLock);
419 result = OCSetPropertyValue(type, propName.c_str(), (void *)propValue.c_str());
424 OCStackResult InProcServerWrapper::getPropertyValue(OCPayloadType type, const std::string& propName,
425 std::string& propValue)
427 auto cLock = m_csdkLock.lock();
428 OCStackResult result = OC_STACK_ERROR;
431 std::lock_guard<std::recursive_mutex> lock(*cLock);
432 result = OCGetPropertyValue(type, propName.c_str(), (void **)propValue.c_str());
437 OCStackResult InProcServerWrapper::registerResource(
438 OCResourceHandle& resourceHandle,
439 std::string& resourceURI,
440 const std::string& resourceTypeName,
441 const std::string& resourceInterface,
442 EntityHandler& eHandler,
443 uint8_t resourceProperties)
446 OCStackResult result = OC_STACK_ERROR;
448 auto cLock = m_csdkLock.lock();
452 std::lock_guard<std::recursive_mutex> lock(*cLock);
456 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
457 resourceTypeName.c_str(), // const char * resourceTypeName
458 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
459 resourceURI.c_str(), // const char * uri
460 EntityHandlerWrapper, // OCEntityHandler entityHandler
462 resourceProperties // uint8_t resourceProperties
467 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
468 resourceTypeName.c_str(), // const char * resourceTypeName
469 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
470 resourceURI.c_str(), // const char * uri
471 NULL, // OCEntityHandler entityHandler
473 resourceProperties // uint8_t resourceProperties
477 if(result != OC_STACK_OK)
479 resourceHandle = (OCResourceHandle) 0;
483 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
484 OC::details::entityHandlerMap[resourceHandle] = eHandler;
485 OC::details::resourceUriMap[resourceHandle] = resourceURI;
490 result = OC_STACK_ERROR;
498 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
499 (EntityHandler entityHandler)
501 OCStackResult result = OC_STACK_ERROR;
504 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
505 OC::details::defaultDeviceEntityHandler = entityHandler;
510 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
514 // If Null passed we unset
515 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
521 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
523 auto cLock = m_csdkLock.lock();
524 OCStackResult result = OC_STACK_ERROR;
528 std::lock_guard<std::recursive_mutex> lock(*cLock);
529 result = OCDeleteResource(resourceHandle);
531 if(result == OC_STACK_OK)
533 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
534 OC::details::resourceUriMap.erase(resourceHandle);
538 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
543 result = OC_STACK_ERROR;
549 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
550 const std::string& resourceTypeName)
552 auto cLock = m_csdkLock.lock();
553 OCStackResult result;
556 std::lock_guard<std::recursive_mutex> lock(*cLock);
557 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
561 result = OC_STACK_ERROR;
564 if (result != OC_STACK_OK)
566 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
571 OCStackResult InProcServerWrapper::resetResourceTypes(const OCResourceHandle& resourceHandle,
572 const std::string& newResourceType)
574 auto cLock = m_csdkLock.lock();
575 OCStackResult result;
578 std::lock_guard<std::recursive_mutex> lock(*cLock);
579 result = OCResetResourceTypes(resourceHandle, newResourceType.c_str());
583 result = OC_STACK_ERROR;
586 if (result != OC_STACK_OK)
588 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
593 OCStackResult InProcServerWrapper::bindInterfaceToResource(
594 const OCResourceHandle& resourceHandle,
595 const std::string& resourceInterfaceName)
597 auto cLock = m_csdkLock.lock();
598 OCStackResult result;
601 std::lock_guard<std::recursive_mutex> lock(*cLock);
602 result = OCBindResourceInterfaceToResource(resourceHandle,
603 resourceInterfaceName.c_str());
607 result = OC_STACK_ERROR;
610 if (result != OC_STACK_OK)
612 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
617 OCStackResult InProcServerWrapper::resetResourceInterfaces(
618 const OCResourceHandle& resourceHandle,
619 const std::string& newResourceInterface)
621 auto cLock = m_csdkLock.lock();
622 OCStackResult result;
625 std::lock_guard<std::recursive_mutex> lock(*cLock);
626 result = OCResetResourceInterfaces(resourceHandle,
627 newResourceInterface.c_str());
631 result = OC_STACK_ERROR;
634 if (result != OC_STACK_OK)
636 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
641 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
644 auto cLock = m_csdkLock.lock();
645 OCStackResult result = OC_STACK_ERROR;
648 std::lock_guard<std::recursive_mutex> lock(*cLock);
649 result = OCStartPresence(seconds);
652 if(result != OC_STACK_OK)
654 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
658 return OC_STACK_NOT_IMPLEMENTED;
662 OCStackResult InProcServerWrapper::stopPresence()
665 auto cLock = m_csdkLock.lock();
666 OCStackResult result = OC_STACK_ERROR;
669 std::lock_guard<std::recursive_mutex> lock(*cLock);
670 result = OCStopPresence();
673 if(result != OC_STACK_OK)
675 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
679 return OC_STACK_NOT_IMPLEMENTED;
683 OCStackResult InProcServerWrapper::sendResponse(
684 const std::shared_ptr<OCResourceResponse> pResponse)
686 auto cLock = m_csdkLock.lock();
687 OCStackResult result = OC_STACK_ERROR;
691 result = OC_STACK_MALFORMED_RESPONSE;
692 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
696 OCEntityHandlerResponse response;
697 // OCRepPayload* payLoad = pResponse->getPayload();
698 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
700 response.requestHandle = pResponse->getRequestHandle();
701 response.resourceHandle = pResponse->getResourceHandle();
702 response.ehResult = pResponse->getResponseResult();
704 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
706 response.persistentBufferFlag = 0;
708 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
710 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
712 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
713 response.sendVendorSpecificHeaderOptions[i].optionID =
714 static_cast<uint16_t>(it->getOptionID());
715 response.sendVendorSpecificHeaderOptions[i].optionLength =
716 (it->getOptionData()).length() + 1;
717 std::string optionData = it->getOptionData();
718 std::copy(optionData.begin(),
720 response.sendVendorSpecificHeaderOptions[i].optionData);
721 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
726 if(OC_EH_RESOURCE_CREATED == response.ehResult)
728 pResponse->getNewResourceUri().copy(response.resourceUri,
729 sizeof (response.resourceUri) - 1);
730 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
735 std::lock_guard<std::recursive_mutex> lock(*cLock);
736 result = OCDoResponse(&response);
740 result = OC_STACK_ERROR;
743 if(result != OC_STACK_OK)
745 oclog() << "Error sending response\n";
748 OCPayloadDestroy(response.payload);
753 OCStackResult InProcServerWrapper::notifyAllObservers(OCResourceHandle resourceHandle,
754 QualityOfService QoS)
756 auto cLock = m_csdkLock.lock();
757 OCStackResult result = OC_STACK_ERROR;
760 std::lock_guard<std::recursive_mutex> lock(*cLock);
761 result = OCNotifyAllObservers(resourceHandle, static_cast<OCQualityOfService>(QoS));
767 OCStackResult InProcServerWrapper::notifyListOfObservers(OCResourceHandle resourceHandle,
768 ObservationIds& observationIds,
769 const std::shared_ptr<OCResourceResponse> pResponse,
770 QualityOfService QoS)
774 return OC_STACK_ERROR;
777 auto cLock = m_csdkLock.lock();
778 OCStackResult result = OC_STACK_ERROR;
781 std::lock_guard<std::recursive_mutex> lock(*cLock);
783 OCRepPayload* pl = pResponse->getResourceRepresentation().getPayload();
784 result = OCNotifyListOfObservers(resourceHandle,
786 observationIds.size(),
788 static_cast<OCQualityOfService>(QoS));
789 OCRepPayloadDestroy(pl);
792 if (result != OC_STACK_OK)
794 throw OCException(OC::Exception::NOTIFY_LIST_OBSERVERS_FAILED, result);
799 InProcServerWrapper::~InProcServerWrapper()
805 catch (InitializeException &e)
807 OIC_LOG_V(INFO, TAG, "Exception in stop (%s)", e.what());