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>
36 #include <OCPlatform.h>
37 #include <OCUtilities.h>
46 std::mutex serverWrapperLock;
47 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
48 std::map <OCResourceHandle, std::string> resourceUriMap;
49 EntityHandler defaultDeviceEntityHandler = 0;
53 void formResourceRequest(OCEntityHandlerFlag flag,
54 OCEntityHandlerRequest * entityHandlerRequest,
55 std::shared_ptr<OCResourceRequest> pRequest)
57 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
58 pRequest->setResourceHandle(entityHandlerRequest->resource);
60 if(flag & OC_INIT_FLAG)
62 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
65 if(flag & OC_REQUEST_FLAG)
67 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
69 if(entityHandlerRequest)
71 if(entityHandlerRequest->query)
73 OC::Utilities::QueryParamsKeyVal qp =
74 OC::Utilities::getQueryParams(
75 reinterpret_cast<char*>(entityHandlerRequest->query));
79 pRequest->setQueryParams(qp);
82 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
84 //Set the header options here.
86 std::string optionData;
87 HeaderOptions headerOptions;
90 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
93 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
94 optionData = reinterpret_cast<const char*>
95 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
96 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
97 headerOptions.push_back(headerOption);
99 pRequest->setHeaderOptions(headerOptions);
102 if(OC_REST_GET == entityHandlerRequest->method)
104 pRequest->setRequestType(OC::PlatformCommands::GET);
106 else if(OC_REST_PUT == entityHandlerRequest->method)
108 pRequest->setRequestType(OC::PlatformCommands::PUT);
109 pRequest->setPayload(std::string(reinterpret_cast<const char*>
110 (entityHandlerRequest->reqJSONPayload)));
112 else if(OC_REST_POST == entityHandlerRequest->method)
114 pRequest->setRequestType(OC::PlatformCommands::POST);
115 pRequest->setPayload(std::string(reinterpret_cast<const char*>
116 (entityHandlerRequest->reqJSONPayload)));
118 else if(OC_REST_DELETE == entityHandlerRequest->method)
120 pRequest->setRequestType(OC::PlatformCommands::DELETE);
125 if(flag & OC_OBSERVE_FLAG)
127 pRequest->setRequestHandlerFlag(
128 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
130 if(entityHandlerRequest)
132 OC::ObservationInfo observationInfo;
133 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
134 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
135 pRequest->setObservationInfo(observationInfo);
140 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
141 OCEntityHandlerRequest * entityHandlerRequest,
144 OCEntityHandlerResult result = OC_EH_ERROR;
146 OC::oclog() << "In Default device entity handler wrapper";
148 if(NULL == entityHandlerRequest)
150 oclog() << "Entity handler request is NULL.";
154 auto pRequest = std::make_shared<OC::OCResourceRequest>();
156 formResourceRequest(flag, entityHandlerRequest, pRequest);
158 pRequest->setResourceUri(std::string(uri));
160 EntityHandler defHandler;
162 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
163 defHandler = OC::details::defaultDeviceEntityHandler;
168 result = defHandler(pRequest);
172 oclog() << "Default device entity handler was not set.";
180 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
181 OCEntityHandlerRequest * entityHandlerRequest)
183 OCEntityHandlerResult result = OC_EH_ERROR;
185 oclog() << "\nIn entity handler wrapper: " << endl;
187 if(NULL == entityHandlerRequest)
189 oclog() << "Entity handler request is NULL." << endl;
193 auto pRequest = std::make_shared<OC::OCResourceRequest>();
195 formResourceRequest(flag, entityHandlerRequest, pRequest);
197 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
198 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
200 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
201 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
202 resourceUriEnd = OC::details::resourceUriMap.end();
204 // Finding the corresponding URI for a resource handle and set the URI in the request
205 if(resourceUriEntry != resourceUriEnd)
207 pRequest->setResourceUri(resourceUriEntry->second);
211 oclog() << "Resource handle not found; Resource URI not set in request";
215 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
216 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
218 // Finding the corresponding CPP Application entityHandler for a given resource
219 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
220 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
221 entityHandlerEnd = OC::details::entityHandlerMap.end();
224 if(entityHandlerEntry != entityHandlerEnd)
226 // Call CPP Application Entity Handler
227 if(entityHandlerEntry->second)
229 result = entityHandlerEntry->second(pRequest);
233 oclog() << "C stack should not call again for parent resource\n";
239 oclog() << "No entity handler found." << endl;
248 InProcServerWrapper::InProcServerWrapper(
249 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
250 : m_csdkLock(csdkLock)
254 if(cfg.mode == ModeType::Server)
256 initType = OC_SERVER;
258 else if (cfg.mode == ModeType::Both)
260 initType = OC_CLIENT_SERVER;
264 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
265 OC_STACK_INVALID_PARAM);
268 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
270 if(OC_STACK_OK != result)
272 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
276 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
279 void InProcServerWrapper::processFunc()
281 auto cLock = m_csdkLock.lock();
282 while(cLock && m_threadRun)
284 OCStackResult result;
287 std::lock_guard<std::recursive_mutex> lock(*cLock);
288 result = OCProcess();
291 // ...the value of variable result is simply ignored for now.
292 if(OC_STACK_ERROR == result)
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::registerResource(
312 OCResourceHandle& resourceHandle,
313 std::string& resourceURI,
314 const std::string& resourceTypeName,
315 const std::string& resourceInterface,
316 EntityHandler& eHandler,
317 uint8_t resourceProperties)
320 OCStackResult result = OC_STACK_ERROR;
322 auto cLock = m_csdkLock.lock();
326 std::lock_guard<std::recursive_mutex> lock(*cLock);
330 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
331 resourceTypeName.c_str(), // const char * resourceTypeName
332 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
333 resourceURI.c_str(), // const char * uri
334 EntityHandlerWrapper, // OCEntityHandler entityHandler
335 resourceProperties // uint8_t resourceProperties
340 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
341 resourceTypeName.c_str(), // const char * resourceTypeName
342 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
343 resourceURI.c_str(), // const char * uri
344 NULL, // OCEntityHandler entityHandler
345 resourceProperties // uint8_t resourceProperties
349 if(result != OC_STACK_OK)
351 resourceHandle = (OCResourceHandle) 0;
355 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
356 OC::details::entityHandlerMap[resourceHandle] = eHandler;
357 OC::details::resourceUriMap[resourceHandle] = resourceURI;
362 result = OC_STACK_ERROR;
368 OCStackResult InProcServerWrapper::registerResourceWithHost(
369 OCResourceHandle& resourceHandle,
370 std::string& resourceHOST,
371 std::string& resourceURI,
372 const std::string& resourceTypeName,
373 const std::string& resourceInterface,
374 EntityHandler& eHandler,
375 uint8_t resourceProperties)
378 OCStackResult result = OC_STACK_ERROR;
380 auto cLock = m_csdkLock.lock();
384 std::lock_guard < std::recursive_mutex > lock(*cLock);
386 if (NULL != eHandler)
388 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
389 resourceTypeName.c_str(), // const char * resourceTypeName
390 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
391 resourceHOST.c_str(), // const char * host
392 (resourceHOST + resourceURI).c_str(), // const char * uri
393 EntityHandlerWrapper, // OCEntityHandler entityHandler
394 resourceProperties // uint8_t resourceProperties
399 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
400 resourceTypeName.c_str(), // const char * resourceTypeName
401 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
402 resourceHOST.c_str(), // const char * host
403 (resourceHOST + resourceURI).c_str(), // const char * uri
404 nullptr, // OCEntityHandler entityHandler
405 resourceProperties // uint8_t resourceProperties
409 if (result != OC_STACK_OK)
411 resourceHandle = nullptr;
415 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
416 OC::details::entityHandlerMap[resourceHandle] = eHandler;
417 OC::details::resourceUriMap[resourceHandle] = resourceURI;
422 result = OC_STACK_ERROR;
428 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
429 (EntityHandler entityHandler)
431 OCStackResult result = OC_STACK_ERROR;
434 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
435 OC::details::defaultDeviceEntityHandler = entityHandler;
440 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
444 // If Null passed we unset
445 result = OCSetDefaultDeviceEntityHandler(NULL);
451 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
453 auto cLock = m_csdkLock.lock();
454 OCStackResult result = OC_STACK_ERROR;
458 std::lock_guard<std::recursive_mutex> lock(*cLock);
459 result = OCDeleteResource(resourceHandle);
461 if(result == OC_STACK_OK)
463 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
464 OC::details::resourceUriMap.erase(resourceHandle);
468 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
473 result = OC_STACK_ERROR;
479 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
480 const std::string& resourceTypeName)
482 auto cLock = m_csdkLock.lock();
483 OCStackResult result;
486 std::lock_guard<std::recursive_mutex> lock(*cLock);
487 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
491 result = OC_STACK_ERROR;
494 if (result != OC_STACK_OK)
496 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
501 OCStackResult InProcServerWrapper::bindInterfaceToResource(
502 const OCResourceHandle& resourceHandle,
503 const std::string& resourceInterfaceName)
505 auto cLock = m_csdkLock.lock();
506 OCStackResult result;
509 std::lock_guard<std::recursive_mutex> lock(*cLock);
510 result = OCBindResourceInterfaceToResource(resourceHandle,
511 resourceInterfaceName.c_str());
515 result = OC_STACK_ERROR;
518 if (result != OC_STACK_OK)
520 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
525 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
527 auto cLock = m_csdkLock.lock();
528 OCStackResult result = OC_STACK_ERROR;
531 std::lock_guard<std::recursive_mutex> lock(*cLock);
532 result = OCStartPresence(seconds);
535 if(result != OC_STACK_OK)
537 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
542 OCStackResult InProcServerWrapper::stopPresence()
544 auto cLock = m_csdkLock.lock();
545 OCStackResult result = OC_STACK_ERROR;
548 std::lock_guard<std::recursive_mutex> lock(*cLock);
549 result = OCStopPresence();
552 if(result != OC_STACK_OK)
554 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
559 OCStackResult InProcServerWrapper::sendResponse(
560 const std::shared_ptr<OCResourceResponse> pResponse)
562 auto cLock = m_csdkLock.lock();
563 OCStackResult result = OC_STACK_ERROR;
567 result = OC_STACK_MALFORMED_RESPONSE;
568 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
572 OCEntityHandlerResponse response;
574 HeaderOptions serverHeaderOptions;
576 payLoad = pResponse->getPayload();
577 serverHeaderOptions = pResponse->getHeaderOptions();
579 response.requestHandle = pResponse->getRequestHandle();
580 response.resourceHandle = pResponse->getResourceHandle();
581 response.ehResult = pResponse->getResponseResult();
582 response.payload = (unsigned char*) payLoad.c_str();
583 response.payloadSize = payLoad.length() + 1;
584 response.persistentBufferFlag = 0;
586 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
588 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
590 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
591 response.sendVendorSpecificHeaderOptions[i].optionID =
592 static_cast<uint16_t>(it->getOptionID());
593 response.sendVendorSpecificHeaderOptions[i].optionLength =
594 (it->getOptionData()).length() + 1;
595 memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
596 (it->getOptionData()).c_str(),
597 (it->getOptionData()).length() + 1);
601 if(OC_EH_RESOURCE_CREATED == response.ehResult)
603 std::string createdUri = pResponse->getNewResourceUri();
604 strncpy(reinterpret_cast<char*>(response.resourceUri),
606 createdUri.length() + 1);
611 std::lock_guard<std::recursive_mutex> lock(*cLock);
612 result = OCDoResponse(&response);
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();