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_INIT_FLAG)
66 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
69 if(flag & OC_REQUEST_FLAG)
71 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
73 if(entityHandlerRequest)
75 if(entityHandlerRequest->query)
77 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
78 entityHandlerRequest->query);
82 pRequest->setQueryParams(qp);
85 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
87 //Set the header options here.
89 std::string optionData;
90 HeaderOptions headerOptions;
93 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
96 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
97 optionData = reinterpret_cast<const char*>
98 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
99 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
100 headerOptions.push_back(headerOption);
102 pRequest->setHeaderOptions(headerOptions);
105 if(OC_REST_GET == entityHandlerRequest->method)
107 pRequest->setRequestType(OC::PlatformCommands::GET);
109 else if(OC_REST_PUT == entityHandlerRequest->method)
111 pRequest->setRequestType(OC::PlatformCommands::PUT);
112 pRequest->setPayload(std::string(reinterpret_cast<const char*>
113 (entityHandlerRequest->reqJSONPayload)));
115 else if(OC_REST_POST == entityHandlerRequest->method)
117 pRequest->setRequestType(OC::PlatformCommands::POST);
118 pRequest->setPayload(std::string(reinterpret_cast<const char*>
119 (entityHandlerRequest->reqJSONPayload)));
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;
138 pRequest->setObservationInfo(observationInfo);
143 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
144 OCEntityHandlerRequest * entityHandlerRequest,
147 OCEntityHandlerResult result = OC_EH_ERROR;
149 OC::oclog() << "In Default device entity handler wrapper";
151 if(NULL == entityHandlerRequest)
153 oclog() << "Entity handler request is NULL.";
157 auto pRequest = std::make_shared<OC::OCResourceRequest>();
159 formResourceRequest(flag, entityHandlerRequest, pRequest);
161 pRequest->setResourceUri(std::string(uri));
163 EntityHandler defHandler;
165 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
166 defHandler = OC::details::defaultDeviceEntityHandler;
171 result = defHandler(pRequest);
175 oclog() << "Default device entity handler was not set.";
183 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
184 OCEntityHandlerRequest * entityHandlerRequest)
186 OCEntityHandlerResult result = OC_EH_ERROR;
188 oclog() << "\nIn entity handler wrapper: " << endl;
190 if(NULL == entityHandlerRequest)
192 oclog() << "Entity handler request is NULL." << endl;
196 auto pRequest = std::make_shared<OC::OCResourceRequest>();
198 formResourceRequest(flag, entityHandlerRequest, pRequest);
200 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
201 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
203 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
204 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
205 resourceUriEnd = OC::details::resourceUriMap.end();
207 // Finding the corresponding URI for a resource handle and set the URI in the request
208 if(resourceUriEntry != resourceUriEnd)
210 pRequest->setResourceUri(resourceUriEntry->second);
214 oclog() << "Resource handle not found; Resource URI not set in request";
218 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
219 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
221 // Finding the corresponding CPP Application entityHandler for a given resource
222 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
223 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
224 entityHandlerEnd = OC::details::entityHandlerMap.end();
227 if(entityHandlerEntry != entityHandlerEnd)
229 // Call CPP Application Entity Handler
230 if(entityHandlerEntry->second)
232 result = entityHandlerEntry->second(pRequest);
236 oclog() << "C stack should not call again for parent resource\n";
242 oclog() << "No entity handler found." << endl;
251 InProcServerWrapper::InProcServerWrapper(
252 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
253 : m_csdkLock(csdkLock)
257 if(cfg.mode == ModeType::Server)
259 initType = OC_SERVER;
261 else if (cfg.mode == ModeType::Both)
263 initType = OC_CLIENT_SERVER;
267 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
268 OC_STACK_INVALID_PARAM);
271 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
273 if(OC_STACK_OK != result)
275 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
279 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
282 void InProcServerWrapper::processFunc()
284 auto cLock = m_csdkLock.lock();
285 while(cLock && m_threadRun)
287 OCStackResult result;
290 std::lock_guard<std::recursive_mutex> lock(*cLock);
291 result = OCProcess();
294 // ...the value of variable result is simply ignored for now.
295 if(OC_STACK_ERROR == result)
298 std::this_thread::sleep_for(std::chrono::milliseconds(10));
302 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
304 auto cLock = m_csdkLock.lock();
305 OCStackResult result = OC_STACK_ERROR;
308 std::lock_guard<std::recursive_mutex> lock(*cLock);
309 result = OCSetDeviceInfo(deviceInfo);
314 OCStackResult InProcServerWrapper::registerResource(
315 OCResourceHandle& resourceHandle,
316 std::string& resourceURI,
317 const std::string& resourceTypeName,
318 const std::string& resourceInterface,
319 EntityHandler& eHandler,
320 uint8_t resourceProperties)
323 OCStackResult result = OC_STACK_ERROR;
325 auto cLock = m_csdkLock.lock();
329 std::lock_guard<std::recursive_mutex> lock(*cLock);
333 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
334 resourceTypeName.c_str(), // const char * resourceTypeName
335 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
336 resourceURI.c_str(), // const char * uri
337 EntityHandlerWrapper, // OCEntityHandler entityHandler
338 resourceProperties // uint8_t resourceProperties
343 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
344 resourceTypeName.c_str(), // const char * resourceTypeName
345 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
346 resourceURI.c_str(), // const char * uri
347 NULL, // OCEntityHandler entityHandler
348 resourceProperties // uint8_t resourceProperties
352 if(result != OC_STACK_OK)
354 resourceHandle = (OCResourceHandle) 0;
358 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
359 OC::details::entityHandlerMap[resourceHandle] = eHandler;
360 OC::details::resourceUriMap[resourceHandle] = resourceURI;
365 result = OC_STACK_ERROR;
371 OCStackResult InProcServerWrapper::registerResourceWithHost(
372 OCResourceHandle& resourceHandle,
373 std::string& resourceHOST,
374 std::string& resourceURI,
375 const std::string& resourceTypeName,
376 const std::string& resourceInterface,
377 EntityHandler& eHandler,
378 uint8_t resourceProperties)
381 OCStackResult result = OC_STACK_ERROR;
383 auto cLock = m_csdkLock.lock();
387 std::lock_guard < std::recursive_mutex > lock(*cLock);
389 if (NULL != eHandler)
391 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
392 resourceTypeName.c_str(), // const char * resourceTypeName
393 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
394 resourceHOST.c_str(), // const char * host
395 (resourceHOST + resourceURI).c_str(), // const char * uri
396 EntityHandlerWrapper, // OCEntityHandler entityHandler
397 resourceProperties // uint8_t resourceProperties
402 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
403 resourceTypeName.c_str(), // const char * resourceTypeName
404 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
405 resourceHOST.c_str(), // const char * host
406 (resourceHOST + resourceURI).c_str(), // const char * uri
407 nullptr, // OCEntityHandler entityHandler
408 resourceProperties // uint8_t resourceProperties
412 if (result != OC_STACK_OK)
414 resourceHandle = nullptr;
418 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
419 OC::details::entityHandlerMap[resourceHandle] = eHandler;
420 OC::details::resourceUriMap[resourceHandle] = resourceURI;
425 result = OC_STACK_ERROR;
431 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
432 (EntityHandler entityHandler)
434 OCStackResult result = OC_STACK_ERROR;
437 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
438 OC::details::defaultDeviceEntityHandler = entityHandler;
443 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
447 // If Null passed we unset
448 result = OCSetDefaultDeviceEntityHandler(NULL);
454 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
456 auto cLock = m_csdkLock.lock();
457 OCStackResult result = OC_STACK_ERROR;
461 std::lock_guard<std::recursive_mutex> lock(*cLock);
462 result = OCDeleteResource(resourceHandle);
464 if(result == OC_STACK_OK)
466 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
467 OC::details::resourceUriMap.erase(resourceHandle);
471 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
476 result = OC_STACK_ERROR;
482 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
483 const std::string& resourceTypeName)
485 auto cLock = m_csdkLock.lock();
486 OCStackResult result;
489 std::lock_guard<std::recursive_mutex> lock(*cLock);
490 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
494 result = OC_STACK_ERROR;
497 if (result != OC_STACK_OK)
499 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
504 OCStackResult InProcServerWrapper::bindInterfaceToResource(
505 const OCResourceHandle& resourceHandle,
506 const std::string& resourceInterfaceName)
508 auto cLock = m_csdkLock.lock();
509 OCStackResult result;
512 std::lock_guard<std::recursive_mutex> lock(*cLock);
513 result = OCBindResourceInterfaceToResource(resourceHandle,
514 resourceInterfaceName.c_str());
518 result = OC_STACK_ERROR;
521 if (result != OC_STACK_OK)
523 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
528 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
530 auto cLock = m_csdkLock.lock();
531 OCStackResult result = OC_STACK_ERROR;
534 std::lock_guard<std::recursive_mutex> lock(*cLock);
535 result = OCStartPresence(seconds);
538 if(result != OC_STACK_OK)
540 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
545 OCStackResult InProcServerWrapper::stopPresence()
547 auto cLock = m_csdkLock.lock();
548 OCStackResult result = OC_STACK_ERROR;
551 std::lock_guard<std::recursive_mutex> lock(*cLock);
552 result = OCStopPresence();
555 if(result != OC_STACK_OK)
557 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
562 OCStackResult InProcServerWrapper::sendResponse(
563 const std::shared_ptr<OCResourceResponse> pResponse)
565 auto cLock = m_csdkLock.lock();
566 OCStackResult result = OC_STACK_ERROR;
570 result = OC_STACK_MALFORMED_RESPONSE;
571 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
575 OCEntityHandlerResponse response;
577 HeaderOptions serverHeaderOptions;
579 payLoad = pResponse->getPayload();
580 serverHeaderOptions = pResponse->getHeaderOptions();
582 response.requestHandle = pResponse->getRequestHandle();
583 response.resourceHandle = pResponse->getResourceHandle();
584 response.ehResult = pResponse->getResponseResult();
586 response.payload = static_cast<char*>(OCMalloc(payLoad.length() + 1));
587 if(!response.payload)
589 result = OC_STACK_NO_MEMORY;
590 throw OCException(OC::Exception::NO_MEMORY, OC_STACK_NO_MEMORY);
593 strncpy(response.payload, payLoad.c_str(), payLoad.length()+1);
594 response.payloadSize = payLoad.length() + 1;
595 response.persistentBufferFlag = 0;
597 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
599 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
601 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
602 response.sendVendorSpecificHeaderOptions[i].optionID =
603 static_cast<uint16_t>(it->getOptionID());
604 response.sendVendorSpecificHeaderOptions[i].optionLength =
605 (it->getOptionData()).length() + 1;
606 memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
607 (it->getOptionData()).c_str(),
608 (it->getOptionData()).length() + 1);
612 if(OC_EH_RESOURCE_CREATED == response.ehResult)
614 std::string createdUri = pResponse->getNewResourceUri();
615 strncpy(reinterpret_cast<char*>(response.resourceUri),
617 createdUri.length() + 1);
622 std::lock_guard<std::recursive_mutex> lock(*cLock);
623 result = OCDoResponse(&response);
627 result = OC_STACK_ERROR;
630 if(result != OC_STACK_OK)
632 oclog() << "Error sending response\n";
638 InProcServerWrapper::~InProcServerWrapper()
640 if(m_processThread.joinable())
643 m_processThread.join();