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>
49 std::mutex serverWrapperLock;
50 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
51 std::map <OCResourceHandle, std::string> resourceUriMap;
52 EntityHandler defaultDeviceEntityHandler;
56 void formResourceRequest(OCEntityHandlerFlag flag,
57 OCEntityHandlerRequest * entityHandlerRequest,
58 std::shared_ptr<OCResourceRequest> pRequest)
60 if(pRequest && entityHandlerRequest)
62 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
63 pRequest->setResourceHandle(entityHandlerRequest->resource);
64 pRequest->setMessageID(entityHandlerRequest->messageID);
67 if(flag & OC_REQUEST_FLAG)
69 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
71 if(entityHandlerRequest)
73 if(entityHandlerRequest->query)
75 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
76 entityHandlerRequest->query);
80 pRequest->setQueryParams(qp);
83 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
85 //Set the header options here.
87 std::string optionData;
88 HeaderOptions headerOptions;
91 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
94 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
95 optionData = reinterpret_cast<const char*>
96 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
97 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
98 headerOptions.push_back(headerOption);
100 pRequest->setHeaderOptions(headerOptions);
103 if(OC_REST_GET == entityHandlerRequest->method)
105 pRequest->setRequestType(OC::PlatformCommands::GET);
107 else if(OC_REST_PUT == entityHandlerRequest->method)
109 pRequest->setRequestType(OC::PlatformCommands::PUT);
110 pRequest->setPayload(entityHandlerRequest->payload);
112 else if(OC_REST_POST == entityHandlerRequest->method)
114 pRequest->setRequestType(OC::PlatformCommands::POST);
115 pRequest->setPayload(entityHandlerRequest->payload);
117 else if(OC_REST_DELETE == entityHandlerRequest->method)
119 pRequest->setRequestType(OC::PlatformCommands::DELETE);
124 if(flag & OC_OBSERVE_FLAG)
126 pRequest->setRequestHandlerFlag(
127 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
129 if(entityHandlerRequest)
131 OC::ObservationInfo observationInfo;
132 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
133 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
135 observationInfo.connectivityType = static_cast<OCConnectivityType>(
136 (entityHandlerRequest->devAddr.adapter << CT_ADAPTER_SHIFT) |
137 (entityHandlerRequest->devAddr.flags & CT_MASK_FLAGS));
138 observationInfo.address = entityHandlerRequest->devAddr.addr;
139 observationInfo.port = entityHandlerRequest->devAddr.port;
140 pRequest->setObservationInfo(observationInfo);
145 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
146 OCEntityHandlerRequest * entityHandlerRequest,
148 void * /*callbackParam*/)
150 OCEntityHandlerResult result = OC_EH_ERROR;
152 OC::oclog() << "In Default device entity handler wrapper";
154 if(NULL == entityHandlerRequest)
156 oclog() << "Entity handler request is NULL.";
160 auto pRequest = std::make_shared<OC::OCResourceRequest>();
162 formResourceRequest(flag, entityHandlerRequest, pRequest);
164 pRequest->setResourceUri(std::string(uri));
166 EntityHandler defHandler;
168 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
169 defHandler = OC::details::defaultDeviceEntityHandler;
174 result = defHandler(pRequest);
178 oclog() << "Default device entity handler was not set.";
186 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
187 OCEntityHandlerRequest * entityHandlerRequest,
188 void* /*callbackParam*/)
190 OCEntityHandlerResult result = OC_EH_ERROR;
192 oclog() << "\nIn entity handler wrapper: " << endl;
194 if(NULL == entityHandlerRequest)
196 oclog() << "Entity handler request is NULL." << endl;
200 auto pRequest = std::make_shared<OC::OCResourceRequest>();
202 formResourceRequest(flag, entityHandlerRequest, pRequest);
204 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
205 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
207 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
208 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
209 resourceUriEnd = OC::details::resourceUriMap.end();
211 // Finding the corresponding URI for a resource handle and set the URI in the request
212 if(resourceUriEntry != resourceUriEnd)
214 pRequest->setResourceUri(resourceUriEntry->second);
218 oclog() << "Resource handle not found; Resource URI not set in request";
222 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
223 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
225 // Finding the corresponding CPP Application entityHandler for a given resource
226 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
227 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
228 entityHandlerEnd = OC::details::entityHandlerMap.end();
231 if(entityHandlerEntry != entityHandlerEnd)
233 // Call CPP Application Entity Handler
234 if(entityHandlerEntry->second)
236 result = entityHandlerEntry->second(pRequest);
240 oclog() << "C stack should not call again for parent resource\n";
246 oclog() << "No entity handler found." << endl;
255 InProcServerWrapper::InProcServerWrapper(
256 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
257 : m_csdkLock(csdkLock)
261 if(cfg.mode == ModeType::Server)
263 initType = OC_SERVER;
265 else if (cfg.mode == ModeType::Both)
267 initType = OC_CLIENT_SERVER;
269 else if (cfg.mode == ModeType::Gateway)
271 initType = OC_GATEWAY;
275 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
276 OC_STACK_INVALID_PARAM);
279 OCTransportFlags serverFlags =
280 static_cast<OCTransportFlags>(cfg.serverConnectivity & CT_MASK_FLAGS);
281 OCTransportFlags clientFlags =
282 static_cast<OCTransportFlags>(cfg.clientConnectivity & CT_MASK_FLAGS);
283 OCStackResult result = OCInit1(initType, serverFlags, clientFlags);
285 if(OC_STACK_OK != result)
287 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
291 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
294 void InProcServerWrapper::processFunc()
296 auto cLock = m_csdkLock.lock();
297 while(cLock && m_threadRun)
299 OCStackResult result;
302 std::lock_guard<std::recursive_mutex> lock(*cLock);
303 result = OCProcess();
306 if(OC_STACK_ERROR == result)
308 oclog() << "OCProcess failed with result " << result <<std::flush;
309 // ...the value of variable result is simply ignored for now.
312 std::this_thread::sleep_for(std::chrono::milliseconds(10));
316 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
318 auto cLock = m_csdkLock.lock();
319 OCStackResult result = OC_STACK_ERROR;
322 std::lock_guard<std::recursive_mutex> lock(*cLock);
323 result = OCSetDeviceInfo(deviceInfo);
328 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
330 auto cLock = m_csdkLock.lock();
331 OCStackResult result = OC_STACK_ERROR;
334 std::lock_guard<std::recursive_mutex> lock(*cLock);
335 result = OCSetPlatformInfo(platformInfo);
340 OCStackResult InProcServerWrapper::setPropertyValue(OCPayloadType type, const std::string& propName,
341 const std::string& propValue)
343 auto cLock = m_csdkLock.lock();
344 OCStackResult result = OC_STACK_ERROR;
347 std::lock_guard<std::recursive_mutex> lock(*cLock);
348 result = OCSetPropertyValue(type, propName.c_str(), (void *)propValue.c_str());
353 OCStackResult InProcServerWrapper::getPropertyValue(OCPayloadType type, const std::string& propName,
354 std::string& propValue)
356 auto cLock = m_csdkLock.lock();
357 OCStackResult result = OC_STACK_ERROR;
360 std::lock_guard<std::recursive_mutex> lock(*cLock);
361 result = OCGetPropertyValue(type, propName.c_str(), (void **)propValue.c_str());
366 OCStackResult InProcServerWrapper::registerResource(
367 OCResourceHandle& resourceHandle,
368 std::string& resourceURI,
369 const std::string& resourceTypeName,
370 const std::string& resourceInterface,
371 EntityHandler& eHandler,
372 uint8_t resourceProperties)
375 OCStackResult result = OC_STACK_ERROR;
377 auto cLock = m_csdkLock.lock();
381 std::lock_guard<std::recursive_mutex> lock(*cLock);
385 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
386 resourceTypeName.c_str(), // const char * resourceTypeName
387 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
388 resourceURI.c_str(), // const char * uri
389 EntityHandlerWrapper, // OCEntityHandler entityHandler
391 resourceProperties // uint8_t resourceProperties
396 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
397 resourceTypeName.c_str(), // const char * resourceTypeName
398 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
399 resourceURI.c_str(), // const char * uri
400 NULL, // OCEntityHandler entityHandler
402 resourceProperties // uint8_t resourceProperties
406 if(result != OC_STACK_OK)
408 resourceHandle = (OCResourceHandle) 0;
412 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
413 OC::details::entityHandlerMap[resourceHandle] = eHandler;
414 OC::details::resourceUriMap[resourceHandle] = resourceURI;
419 result = OC_STACK_ERROR;
427 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
428 (EntityHandler entityHandler)
430 OCStackResult result = OC_STACK_ERROR;
433 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
434 OC::details::defaultDeviceEntityHandler = entityHandler;
439 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
443 // If Null passed we unset
444 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
450 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
452 auto cLock = m_csdkLock.lock();
453 OCStackResult result = OC_STACK_ERROR;
457 std::lock_guard<std::recursive_mutex> lock(*cLock);
458 result = OCDeleteResource(resourceHandle);
460 if(result == OC_STACK_OK)
462 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
463 OC::details::resourceUriMap.erase(resourceHandle);
467 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
472 result = OC_STACK_ERROR;
478 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
479 const std::string& resourceTypeName)
481 auto cLock = m_csdkLock.lock();
482 OCStackResult result;
485 std::lock_guard<std::recursive_mutex> lock(*cLock);
486 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
490 result = OC_STACK_ERROR;
493 if (result != OC_STACK_OK)
495 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
500 OCStackResult InProcServerWrapper::bindInterfaceToResource(
501 const OCResourceHandle& resourceHandle,
502 const std::string& resourceInterfaceName)
504 auto cLock = m_csdkLock.lock();
505 OCStackResult result;
508 std::lock_guard<std::recursive_mutex> lock(*cLock);
509 result = OCBindResourceInterfaceToResource(resourceHandle,
510 resourceInterfaceName.c_str());
514 result = OC_STACK_ERROR;
517 if (result != OC_STACK_OK)
519 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
524 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
526 auto cLock = m_csdkLock.lock();
527 OCStackResult result = OC_STACK_ERROR;
530 std::lock_guard<std::recursive_mutex> lock(*cLock);
531 result = OCStartPresence(seconds);
534 if(result != OC_STACK_OK)
536 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
541 OCStackResult InProcServerWrapper::stopPresence()
543 auto cLock = m_csdkLock.lock();
544 OCStackResult result = OC_STACK_ERROR;
547 std::lock_guard<std::recursive_mutex> lock(*cLock);
548 result = OCStopPresence();
551 if(result != OC_STACK_OK)
553 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
558 OCStackResult InProcServerWrapper::sendResponse(
559 const std::shared_ptr<OCResourceResponse> pResponse)
561 auto cLock = m_csdkLock.lock();
562 OCStackResult result = OC_STACK_ERROR;
566 result = OC_STACK_MALFORMED_RESPONSE;
567 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
571 OCEntityHandlerResponse response;
572 // OCRepPayload* payLoad = pResponse->getPayload();
573 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
575 response.requestHandle = pResponse->getRequestHandle();
576 response.resourceHandle = pResponse->getResourceHandle();
577 response.ehResult = pResponse->getResponseResult();
579 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
581 response.persistentBufferFlag = 0;
583 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
585 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
587 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
588 response.sendVendorSpecificHeaderOptions[i].optionID =
589 static_cast<uint16_t>(it->getOptionID());
590 response.sendVendorSpecificHeaderOptions[i].optionLength =
591 (it->getOptionData()).length() + 1;
592 std::string optionData = it->getOptionData();
593 std::copy(optionData.begin(),
595 response.sendVendorSpecificHeaderOptions[i].optionData);
596 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
601 if(OC_EH_RESOURCE_CREATED == response.ehResult)
603 pResponse->getNewResourceUri().copy(response.resourceUri,
604 sizeof (response.resourceUri) - 1);
605 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
610 std::lock_guard<std::recursive_mutex> lock(*cLock);
611 result = OCDoResponse(&response);
615 OICFree(response.payload);
616 result = OC_STACK_ERROR;
619 if(result != OC_STACK_OK)
621 oclog() << "Error sending response\n";
627 InProcServerWrapper::~InProcServerWrapper()
629 if(m_processThread.joinable())
632 m_processThread.join();