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>
37 #include <OCPlatform.h>
38 #include <OCUtilities.h>
47 std::mutex serverWrapperLock;
48 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
49 std::map <OCResourceHandle, std::string> resourceUriMap;
50 EntityHandler defaultDeviceEntityHandler = 0;
54 void formResourceRequest(OCEntityHandlerFlag flag,
55 OCEntityHandlerRequest * entityHandlerRequest,
56 std::shared_ptr<OCResourceRequest> pRequest)
58 if(pRequest && entityHandlerRequest)
60 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
61 pRequest->setResourceHandle(entityHandlerRequest->resource);
64 if(flag & OC_REQUEST_FLAG)
66 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
68 if(entityHandlerRequest)
70 if(entityHandlerRequest->query)
72 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
73 entityHandlerRequest->query);
77 pRequest->setQueryParams(qp);
80 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
82 //Set the header options here.
84 std::string optionData;
85 HeaderOptions headerOptions;
88 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
91 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
92 optionData = reinterpret_cast<const char*>
93 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
94 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
95 headerOptions.push_back(headerOption);
97 pRequest->setHeaderOptions(headerOptions);
100 if(OC_REST_GET == entityHandlerRequest->method)
102 pRequest->setRequestType(OC::PlatformCommands::GET);
104 else if(OC_REST_PUT == entityHandlerRequest->method)
106 pRequest->setRequestType(OC::PlatformCommands::PUT);
107 pRequest->setPayload(std::string(reinterpret_cast<const char*>
108 (entityHandlerRequest->reqJSONPayload)));
110 else if(OC_REST_POST == entityHandlerRequest->method)
112 pRequest->setRequestType(OC::PlatformCommands::POST);
113 pRequest->setPayload(std::string(reinterpret_cast<const char*>
114 (entityHandlerRequest->reqJSONPayload)));
116 else if(OC_REST_DELETE == entityHandlerRequest->method)
118 pRequest->setRequestType(OC::PlatformCommands::DELETE);
123 if(flag & OC_OBSERVE_FLAG)
125 pRequest->setRequestHandlerFlag(
126 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
128 if(entityHandlerRequest)
130 OC::ObservationInfo observationInfo;
131 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
132 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
133 pRequest->setObservationInfo(observationInfo);
138 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
139 OCEntityHandlerRequest * entityHandlerRequest,
142 OCEntityHandlerResult result = OC_EH_ERROR;
144 OC::oclog() << "In Default device entity handler wrapper";
146 if(NULL == entityHandlerRequest)
148 oclog() << "Entity handler request is NULL.";
152 auto pRequest = std::make_shared<OC::OCResourceRequest>();
154 formResourceRequest(flag, entityHandlerRequest, pRequest);
156 pRequest->setResourceUri(std::string(uri));
158 EntityHandler defHandler;
160 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
161 defHandler = OC::details::defaultDeviceEntityHandler;
166 result = defHandler(pRequest);
170 oclog() << "Default device entity handler was not set.";
178 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
179 OCEntityHandlerRequest * entityHandlerRequest)
181 OCEntityHandlerResult result = OC_EH_ERROR;
183 oclog() << "\nIn entity handler wrapper: " << endl;
185 if(NULL == entityHandlerRequest)
187 oclog() << "Entity handler request is NULL." << endl;
191 auto pRequest = std::make_shared<OC::OCResourceRequest>();
193 formResourceRequest(flag, entityHandlerRequest, pRequest);
195 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
196 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
198 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
199 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
200 resourceUriEnd = OC::details::resourceUriMap.end();
202 // Finding the corresponding URI for a resource handle and set the URI in the request
203 if(resourceUriEntry != resourceUriEnd)
205 pRequest->setResourceUri(resourceUriEntry->second);
209 oclog() << "Resource handle not found; Resource URI not set in request";
213 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
214 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
216 // Finding the corresponding CPP Application entityHandler for a given resource
217 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
218 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
219 entityHandlerEnd = OC::details::entityHandlerMap.end();
222 if(entityHandlerEntry != entityHandlerEnd)
224 // Call CPP Application Entity Handler
225 if(entityHandlerEntry->second)
227 result = entityHandlerEntry->second(pRequest);
231 oclog() << "C stack should not call again for parent resource\n";
237 oclog() << "No entity handler found." << endl;
246 InProcServerWrapper::InProcServerWrapper(
247 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
248 : m_csdkLock(csdkLock)
252 if(cfg.mode == ModeType::Server)
254 initType = OC_SERVER;
256 else if (cfg.mode == ModeType::Both)
258 initType = OC_CLIENT_SERVER;
262 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
263 OC_STACK_INVALID_PARAM);
266 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
268 if(OC_STACK_OK != result)
270 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
274 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
277 void InProcServerWrapper::processFunc()
279 auto cLock = m_csdkLock.lock();
280 while(cLock && m_threadRun)
282 OCStackResult result;
285 std::lock_guard<std::recursive_mutex> lock(*cLock);
286 result = OCProcess();
289 if(OC_STACK_ERROR == result)
291 oclog() << "OCProcess failed with result " << result <<std::flush;
292 // ...the value of variable result is simply ignored for now.
295 std::this_thread::sleep_for(std::chrono::milliseconds(10));
299 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
301 auto cLock = m_csdkLock.lock();
302 OCStackResult result = OC_STACK_ERROR;
305 std::lock_guard<std::recursive_mutex> lock(*cLock);
306 result = OCSetDeviceInfo(deviceInfo);
311 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
313 auto cLock = m_csdkLock.lock();
314 OCStackResult result = OC_STACK_ERROR;
317 std::lock_guard<std::recursive_mutex> lock(*cLock);
318 result = OCSetPlatformInfo(platformInfo);
323 OCStackResult InProcServerWrapper::registerResource(
324 OCResourceHandle& resourceHandle,
325 std::string& resourceURI,
326 const std::string& resourceTypeName,
327 const std::string& resourceInterface,
328 EntityHandler& eHandler,
329 uint8_t resourceProperties)
332 OCStackResult result = OC_STACK_ERROR;
334 auto cLock = m_csdkLock.lock();
338 std::lock_guard<std::recursive_mutex> lock(*cLock);
342 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
343 resourceTypeName.c_str(), // const char * resourceTypeName
344 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
345 resourceURI.c_str(), // const char * uri
346 EntityHandlerWrapper, // OCEntityHandler entityHandler
347 resourceProperties // uint8_t resourceProperties
352 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
353 resourceTypeName.c_str(), // const char * resourceTypeName
354 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
355 resourceURI.c_str(), // const char * uri
356 NULL, // OCEntityHandler entityHandler
357 resourceProperties // uint8_t resourceProperties
361 if(result != OC_STACK_OK)
363 resourceHandle = (OCResourceHandle) 0;
367 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
368 OC::details::entityHandlerMap[resourceHandle] = eHandler;
369 OC::details::resourceUriMap[resourceHandle] = resourceURI;
374 result = OC_STACK_ERROR;
380 OCStackResult InProcServerWrapper::registerResourceWithHost(
381 OCResourceHandle& resourceHandle,
382 std::string& resourceHOST,
383 std::string& resourceURI,
384 const std::string& resourceTypeName,
385 const std::string& resourceInterface,
386 EntityHandler& eHandler,
387 uint8_t resourceProperties)
390 OCStackResult result = OC_STACK_ERROR;
392 auto cLock = m_csdkLock.lock();
396 std::lock_guard < std::recursive_mutex > lock(*cLock);
398 if (NULL != eHandler)
400 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
401 resourceTypeName.c_str(), // const char * resourceTypeName
402 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
403 resourceHOST.c_str(), // const char * host
404 (resourceHOST + resourceURI).c_str(), // const char * uri
405 EntityHandlerWrapper, // OCEntityHandler entityHandler
406 resourceProperties // uint8_t resourceProperties
411 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
412 resourceTypeName.c_str(), // const char * resourceTypeName
413 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
414 resourceHOST.c_str(), // const char * host
415 (resourceHOST + resourceURI).c_str(), // const char * uri
416 nullptr, // OCEntityHandler entityHandler
417 resourceProperties // uint8_t resourceProperties
421 if (result != OC_STACK_OK)
423 resourceHandle = nullptr;
427 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
428 OC::details::entityHandlerMap[resourceHandle] = eHandler;
429 OC::details::resourceUriMap[resourceHandle] = resourceURI;
434 result = OC_STACK_ERROR;
440 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
441 (EntityHandler entityHandler)
443 OCStackResult result = OC_STACK_ERROR;
446 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
447 OC::details::defaultDeviceEntityHandler = entityHandler;
452 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
456 // If Null passed we unset
457 result = OCSetDefaultDeviceEntityHandler(NULL);
463 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
465 auto cLock = m_csdkLock.lock();
466 OCStackResult result = OC_STACK_ERROR;
470 std::lock_guard<std::recursive_mutex> lock(*cLock);
471 result = OCDeleteResource(resourceHandle);
473 if(result == OC_STACK_OK)
475 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
476 OC::details::resourceUriMap.erase(resourceHandle);
480 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
485 result = OC_STACK_ERROR;
491 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
492 const std::string& resourceTypeName)
494 auto cLock = m_csdkLock.lock();
495 OCStackResult result;
498 std::lock_guard<std::recursive_mutex> lock(*cLock);
499 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
503 result = OC_STACK_ERROR;
506 if (result != OC_STACK_OK)
508 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
513 OCStackResult InProcServerWrapper::bindInterfaceToResource(
514 const OCResourceHandle& resourceHandle,
515 const std::string& resourceInterfaceName)
517 auto cLock = m_csdkLock.lock();
518 OCStackResult result;
521 std::lock_guard<std::recursive_mutex> lock(*cLock);
522 result = OCBindResourceInterfaceToResource(resourceHandle,
523 resourceInterfaceName.c_str());
527 result = OC_STACK_ERROR;
530 if (result != OC_STACK_OK)
532 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
537 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
539 auto cLock = m_csdkLock.lock();
540 OCStackResult result = OC_STACK_ERROR;
543 std::lock_guard<std::recursive_mutex> lock(*cLock);
544 result = OCStartPresence(seconds);
547 if(result != OC_STACK_OK)
549 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
554 OCStackResult InProcServerWrapper::stopPresence()
556 auto cLock = m_csdkLock.lock();
557 OCStackResult result = OC_STACK_ERROR;
560 std::lock_guard<std::recursive_mutex> lock(*cLock);
561 result = OCStopPresence();
564 if(result != OC_STACK_OK)
566 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
571 OCStackResult InProcServerWrapper::sendResponse(
572 const std::shared_ptr<OCResourceResponse> pResponse)
574 auto cLock = m_csdkLock.lock();
575 OCStackResult result = OC_STACK_ERROR;
579 result = OC_STACK_MALFORMED_RESPONSE;
580 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
584 OCEntityHandlerResponse response;
586 HeaderOptions serverHeaderOptions;
588 payLoad = pResponse->getPayload();
589 serverHeaderOptions = pResponse->getHeaderOptions();
591 response.requestHandle = pResponse->getRequestHandle();
592 response.resourceHandle = pResponse->getResourceHandle();
593 response.ehResult = pResponse->getResponseResult();
595 response.payload = static_cast<char*>(OCMalloc(payLoad.length() + 1));
596 if(!response.payload)
598 result = OC_STACK_NO_MEMORY;
599 throw OCException(OC::Exception::NO_MEMORY, OC_STACK_NO_MEMORY);
602 strncpy(response.payload, payLoad.c_str(), payLoad.length()+1);
603 response.payloadSize = payLoad.length() + 1;
604 response.persistentBufferFlag = 0;
606 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
608 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
610 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
611 response.sendVendorSpecificHeaderOptions[i].optionID =
612 static_cast<uint16_t>(it->getOptionID());
613 response.sendVendorSpecificHeaderOptions[i].optionLength =
614 (it->getOptionData()).length() + 1;
615 memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
616 (it->getOptionData()).c_str(),
617 (it->getOptionData()).length() + 1);
621 if(OC_EH_RESOURCE_CREATED == response.ehResult)
623 std::string createdUri = pResponse->getNewResourceUri();
624 strncpy(reinterpret_cast<char*>(response.resourceUri),
626 createdUri.length() + 1);
631 std::lock_guard<std::recursive_mutex> lock(*cLock);
632 result = OCDoResponse(&response);
636 OCFree(response.payload);
637 result = OC_STACK_ERROR;
640 if(result != OC_STACK_OK)
642 oclog() << "Error sending response\n";
648 InProcServerWrapper::~InProcServerWrapper()
650 if(m_processThread.joinable())
653 m_processThread.join();