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>
42 std::map <OCResourceHandle, OC::EntityHandler> entityHandlerMap;
43 std::map <OCResourceHandle, std::string> resourceUriMap;
44 EntityHandler defaultDeviceEntityHandler = 0;
46 void formResourceRequest(OCEntityHandlerFlag flag,
47 OCEntityHandlerRequest * entityHandlerRequest,
48 std::shared_ptr<OCResourceRequest> pRequest)
50 pRequest->setRequestHandle(entityHandlerRequest->requestHandle);
51 pRequest->setResourceHandle(entityHandlerRequest->resource);
53 if(flag & OC_INIT_FLAG)
55 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
58 if(flag & OC_REQUEST_FLAG)
60 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
62 if(entityHandlerRequest)
64 if(entityHandlerRequest->query)
66 std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
68 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
72 pRequest->setQueryParams(qp);
75 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
77 //Set the header options here.
79 std::string optionData;
80 HeaderOptions headerOptions;
83 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
86 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
87 optionData = reinterpret_cast<const char*>
88 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
89 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
90 headerOptions.push_back(headerOption);
92 pRequest->setHeaderOptions(headerOptions);
95 if(OC_REST_GET == entityHandlerRequest->method)
97 pRequest->setRequestType(OC::PlatformCommands::GET);
99 else if(OC_REST_PUT == entityHandlerRequest->method)
101 pRequest->setRequestType(OC::PlatformCommands::PUT);
102 pRequest->setPayload(std::string(reinterpret_cast<const char*>
103 (entityHandlerRequest->reqJSONPayload)));
105 else if(OC_REST_POST == entityHandlerRequest->method)
107 pRequest->setRequestType(OC::PlatformCommands::POST);
108 pRequest->setPayload(std::string(reinterpret_cast<const char*>
109 (entityHandlerRequest->reqJSONPayload)));
111 else if(OC_REST_DELETE == entityHandlerRequest->method)
113 pRequest->setRequestType(OC::PlatformCommands::DELETE);
118 if(flag & OC_OBSERVE_FLAG)
120 pRequest->setRequestHandlerFlag(
121 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
123 if(entityHandlerRequest)
125 OC::ObservationInfo observationInfo;
126 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
127 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
128 pRequest->setObservationInfo(observationInfo);
133 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
134 OCEntityHandlerRequest * entityHandlerRequest,
137 OCEntityHandlerResult result = OC_EH_ERROR;
139 OC::oclog() << "In Default device entity handler wrapper";
141 if(NULL == entityHandlerRequest)
143 oclog() << "Entity handler request is NULL.";
147 auto pRequest = std::make_shared<OC::OCResourceRequest>();
149 formResourceRequest(flag, entityHandlerRequest, pRequest);
151 pRequest->setResourceUri(std::string(uri));
153 if(defaultDeviceEntityHandler)
155 result = defaultDeviceEntityHandler(pRequest);
159 oclog() << "Default device entity handler was not set.";
167 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
168 OCEntityHandlerRequest * entityHandlerRequest)
170 OCEntityHandlerResult result = OC_EH_ERROR;
172 oclog() << "\nIn entity handler wrapper: " << endl;
174 if(NULL == entityHandlerRequest)
176 oclog() << "Entity handler request is NULL." << endl;
180 auto pRequest = std::make_shared<OC::OCResourceRequest>();
182 formResourceRequest(flag, entityHandlerRequest, pRequest);
184 // Finding the corresponding URI for a resource handle and set the URI in the request
185 auto resourceUriEntry = resourceUriMap.find(entityHandlerRequest->resource);
186 if(resourceUriEntry != resourceUriMap.end())
188 pRequest->setResourceUri(resourceUriEntry->second);
192 oclog() << "Resource handle not found; Resource URI not set in request";
196 // Finding the corresponding CPP Application entityHandler for a given resource
197 auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);
199 if(entityHandlerEntry != entityHandlerMap.end())
201 // Call CPP Application Entity Handler
202 if(entityHandlerEntry->second)
204 result = entityHandlerEntry->second(pRequest);
208 oclog() << "C stack should not call again for parent resource\n";
214 oclog() << "No entity handler found." << endl;
223 InProcServerWrapper::InProcServerWrapper(
224 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
225 : m_csdkLock(csdkLock)
229 if(cfg.mode == ModeType::Server)
231 initType = OC_SERVER;
233 else if (cfg.mode == ModeType::Both)
235 initType = OC_CLIENT_SERVER;
239 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
240 OC_STACK_INVALID_PARAM);
243 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
245 if(OC_STACK_OK != result)
247 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
251 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
254 void InProcServerWrapper::processFunc()
256 auto cLock = m_csdkLock.lock();
257 while(cLock && m_threadRun)
259 OCStackResult result;
262 std::lock_guard<std::recursive_mutex> lock(*cLock);
263 result = OCProcess();
266 // ...the value of variable result is simply ignored for now.
267 if(OC_STACK_ERROR == result)
270 std::this_thread::sleep_for(std::chrono::milliseconds(10));
274 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
276 auto cLock = m_csdkLock.lock();
277 OCStackResult result = OC_STACK_ERROR;
280 std::lock_guard<std::recursive_mutex> lock(*cLock);
281 result = OCSetDeviceInfo(deviceInfo);
286 OCStackResult InProcServerWrapper::registerResource(
287 OCResourceHandle& resourceHandle,
288 std::string& resourceURI,
289 const std::string& resourceTypeName,
290 const std::string& resourceInterface,
291 EntityHandler& eHandler,
292 uint8_t resourceProperties)
295 OCStackResult result = OC_STACK_ERROR;
297 auto cLock = m_csdkLock.lock();
301 std::lock_guard<std::recursive_mutex> lock(*cLock);
305 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
306 resourceTypeName.c_str(), // const char * resourceTypeName
307 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
308 resourceURI.c_str(), // const char * uri
309 EntityHandlerWrapper, // OCEntityHandler entityHandler
310 resourceProperties // uint8_t resourceProperties
315 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
316 resourceTypeName.c_str(), // const char * resourceTypeName
317 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
318 resourceURI.c_str(), // const char * uri
319 NULL, // OCEntityHandler entityHandler
320 resourceProperties // uint8_t resourceProperties
324 if(result != OC_STACK_OK)
326 resourceHandle = (OCResourceHandle) 0;
330 entityHandlerMap[resourceHandle] = eHandler;
331 resourceUriMap[resourceHandle] = resourceURI;
336 result = OC_STACK_ERROR;
342 OCStackResult InProcServerWrapper::registerResourceWithHost(
343 OCResourceHandle& resourceHandle,
344 std::string& resourceHOST,
345 std::string& resourceURI,
346 const std::string& resourceTypeName,
347 const std::string& resourceInterface,
348 EntityHandler& eHandler,
349 uint8_t resourceProperties)
352 OCStackResult result = OC_STACK_ERROR;
354 auto cLock = m_csdkLock.lock();
358 std::lock_guard < std::recursive_mutex > lock(*cLock);
360 if (NULL != eHandler)
362 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
363 resourceTypeName.c_str(), // const char * resourceTypeName
364 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
365 resourceHOST.c_str(), // const char * host
366 (resourceHOST + resourceURI).c_str(), // const char * uri
367 EntityHandlerWrapper, // OCEntityHandler entityHandler
368 resourceProperties // uint8_t resourceProperties
373 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
374 resourceTypeName.c_str(), // const char * resourceTypeName
375 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
376 resourceHOST.c_str(), // const char * host
377 (resourceHOST + resourceURI).c_str(), // const char * uri
378 nullptr, // OCEntityHandler entityHandler
379 resourceProperties // uint8_t resourceProperties
383 if (result != OC_STACK_OK)
385 resourceHandle = nullptr;
389 entityHandlerMap[resourceHandle] = eHandler;
390 resourceUriMap[resourceHandle] = resourceURI;
395 result = OC_STACK_ERROR;
401 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
402 (EntityHandler entityHandler)
404 OCStackResult result = OC_STACK_ERROR;
406 defaultDeviceEntityHandler = entityHandler;
410 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
414 // If Null passed we unset
415 result = OCSetDefaultDeviceEntityHandler(NULL);
421 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
423 auto cLock = m_csdkLock.lock();
424 OCStackResult result = OC_STACK_ERROR;
428 std::lock_guard<std::recursive_mutex> lock(*cLock);
429 result = OCDeleteResource(resourceHandle);
431 if(result == OC_STACK_OK)
433 resourceUriMap.erase(resourceHandle);
437 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
442 result = OC_STACK_ERROR;
448 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
449 const std::string& resourceTypeName)
451 auto cLock = m_csdkLock.lock();
452 OCStackResult result;
455 std::lock_guard<std::recursive_mutex> lock(*cLock);
456 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
460 result = OC_STACK_ERROR;
463 if (result != OC_STACK_OK)
465 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
470 OCStackResult InProcServerWrapper::bindInterfaceToResource(
471 const OCResourceHandle& resourceHandle,
472 const std::string& resourceInterfaceName)
474 auto cLock = m_csdkLock.lock();
475 OCStackResult result;
478 std::lock_guard<std::recursive_mutex> lock(*cLock);
479 result = OCBindResourceInterfaceToResource(resourceHandle,
480 resourceInterfaceName.c_str());
484 result = OC_STACK_ERROR;
487 if (result != OC_STACK_OK)
489 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
494 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
496 auto cLock = m_csdkLock.lock();
497 OCStackResult result = OC_STACK_ERROR;
500 std::lock_guard<std::recursive_mutex> lock(*cLock);
501 result = OCStartPresence(seconds);
504 if(result != OC_STACK_OK)
506 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
511 OCStackResult InProcServerWrapper::stopPresence()
513 auto cLock = m_csdkLock.lock();
514 OCStackResult result = OC_STACK_ERROR;
517 std::lock_guard<std::recursive_mutex> lock(*cLock);
518 result = OCStopPresence();
521 if(result != OC_STACK_OK)
523 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
528 OCStackResult InProcServerWrapper::sendResponse(
529 const std::shared_ptr<OCResourceResponse> pResponse)
531 auto cLock = m_csdkLock.lock();
532 OCStackResult result = OC_STACK_ERROR;
536 result = OC_STACK_MALFORMED_RESPONSE;
537 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
541 OCEntityHandlerResponse response;
543 HeaderOptions serverHeaderOptions;
545 payLoad = pResponse->getPayload();
546 serverHeaderOptions = pResponse->getHeaderOptions();
548 response.requestHandle = pResponse->getRequestHandle();
549 response.resourceHandle = pResponse->getResourceHandle();
550 response.ehResult = pResponse->getResponseResult();
551 response.payload = (unsigned char*) payLoad.c_str();
552 response.payloadSize = payLoad.length() + 1;
553 response.persistentBufferFlag = 0;
555 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
557 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
559 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
560 response.sendVendorSpecificHeaderOptions[i].optionID =
561 static_cast<uint16_t>(it->getOptionID());
562 response.sendVendorSpecificHeaderOptions[i].optionLength =
563 (it->getOptionData()).length() + 1;
564 memcpy(response.sendVendorSpecificHeaderOptions[i].optionData,
565 (it->getOptionData()).c_str(),
566 (it->getOptionData()).length() + 1);
570 if(OC_EH_RESOURCE_CREATED == response.ehResult)
572 std::string createdUri = pResponse->getNewResourceUri();
573 strncpy(reinterpret_cast<char*>(response.resourceUri),
575 createdUri.length() + 1);
580 std::lock_guard<std::recursive_mutex> lock(*cLock);
581 result = OCDoResponse(&response);
585 result = OC_STACK_ERROR;
588 if(result != OC_STACK_OK)
590 oclog() << "Error sending response\n";
596 InProcServerWrapper::~InProcServerWrapper()
598 if(m_processThread.joinable())
601 m_processThread.join();