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 if(flag & OC_INIT_FLAG)
52 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::InitFlag);
55 if(flag & OC_REQUEST_FLAG)
57 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
59 if(entityHandlerRequest)
61 if(entityHandlerRequest->query)
63 std::string querystr(reinterpret_cast<char*>(entityHandlerRequest->query));
65 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(querystr);
69 pRequest->setQueryParams(qp);
72 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
74 //Set the header options here.
76 std::string optionData;
77 HeaderOptions headerOptions;
80 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
83 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
84 optionData = reinterpret_cast<const char*>
85 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
86 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
87 headerOptions.push_back(headerOption);
89 pRequest->setHeaderOptions(headerOptions);
92 if(OC_REST_GET == entityHandlerRequest->method)
94 pRequest->setRequestType(OC::PlatformCommands::GET);
96 else if(OC_REST_PUT == entityHandlerRequest->method)
98 pRequest->setRequestType(OC::PlatformCommands::PUT);
99 pRequest->setPayload(std::string(reinterpret_cast<const char*>
100 (entityHandlerRequest->reqJSONPayload)));
102 else if(OC_REST_POST == entityHandlerRequest->method)
104 pRequest->setRequestType(OC::PlatformCommands::POST);
105 pRequest->setPayload(std::string(reinterpret_cast<const char*>
106 (entityHandlerRequest->reqJSONPayload)));
108 else if(OC_REST_DELETE == entityHandlerRequest->method)
110 pRequest->setRequestType(OC::PlatformCommands::DELETE);
115 if(flag & OC_OBSERVE_FLAG)
117 pRequest->setRequestHandlerFlag(
118 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
119 if(entityHandlerRequest->obsInfo)
121 OC::ObservationInfo observationInfo;
122 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo->action;
123 observationInfo.obsId = entityHandlerRequest->obsInfo->obsId;
124 pRequest->setObservationInfo(observationInfo);
129 void processResourceResponse(OCEntityHandlerFlag flag,
130 OCEntityHandlerRequest * entityHandlerRequest,
131 std::shared_ptr<OCResourceResponse> pResponse)
133 if(flag & OC_REQUEST_FLAG)
135 // TODO we could use const reference
137 HeaderOptions serverHeaderOptions;
141 payLoad = pResponse->getPayload();
142 serverHeaderOptions = pResponse->getHeaderOptions();
146 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
149 if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen)
152 entityHandlerRequest->numSendVendorSpecificHeaderOptions =
153 serverHeaderOptions.size();
154 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
156 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
157 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionID =
158 static_cast<uint16_t>(it->getOptionID());
159 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionLength =
160 (it->getOptionData()).length() + 1;
161 memcpy(entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionData,
162 (it->getOptionData()).c_str(),
163 (it->getOptionData()).length() + 1);
167 strncpy((char*)entityHandlerRequest->resJSONPayload,
169 entityHandlerRequest->resJSONPayloadLen);
173 throw OCException(OC::Exception::STR_PAYLOAD_OVERFLOW, OC_STACK_MALFORMED_RESPONSE);
179 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
180 OCEntityHandlerRequest * entityHandlerRequest,
183 OCEntityHandlerResult result = OC_EH_ERROR;
185 OC::oclog() << "In Default device entity handler wrapper";
187 if(NULL == entityHandlerRequest)
189 oclog() << "Entity handler request is NULL.";
193 auto pRequest = std::make_shared<OC::OCResourceRequest>();
194 auto pResponse = std::make_shared<OC::OCResourceResponse>();
196 formResourceRequest(flag, entityHandlerRequest, pRequest);
198 pRequest->setResourceUri(std::string(uri));
200 if(defaultDeviceEntityHandler)
202 result = defaultDeviceEntityHandler(pRequest, pResponse);
206 oclog() << "Default device entity handler was not set.";
210 processResourceResponse(flag, entityHandlerRequest, pResponse);
216 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
217 OCEntityHandlerRequest * entityHandlerRequest)
219 OCEntityHandlerResult result = OC_EH_ERROR;
221 oclog() << "\nIn entity handler wrapper: " << endl;
223 if(NULL == entityHandlerRequest)
225 oclog() << "Entity handler request is NULL." << endl;
229 auto pRequest = std::make_shared<OC::OCResourceRequest>();
230 auto pResponse = std::make_shared<OC::OCResourceResponse>();
232 formResourceRequest(flag, entityHandlerRequest, pRequest);
234 // Finding the corresponding URI for a resource handle and set the URI in the request
235 auto resourceUriEntry = resourceUriMap.find(entityHandlerRequest->resource);
236 if(resourceUriEntry != resourceUriMap.end())
238 pRequest->setResourceUri(resourceUriEntry->second);
242 oclog() << "Resource handle not found; Resource URI not set in request";
246 // Finding the corresponding CPP Application entityHandler for a given resource
247 auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);
249 if(entityHandlerEntry != entityHandlerMap.end())
251 // Call CPP Application Entity Handler
252 if(entityHandlerEntry->second)
254 result = entityHandlerEntry->second(pRequest, pResponse);
256 if(OC_EH_RESOURCE_CREATED == result)
258 std::string createdUri = pResponse->getNewResourceUri();
259 strncpy(reinterpret_cast<char*>(entityHandlerRequest->newResourceUri),
261 createdUri.length() + 1);
266 oclog() << "C stack should not call again for parent resource\n";
272 oclog() << "No entity handler found." << endl;
276 processResourceResponse(flag, entityHandlerRequest, pResponse);
283 InProcServerWrapper::InProcServerWrapper(OC::OCPlatform_impl& owner,
284 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
285 : IServerWrapper(owner),
290 if(cfg.mode == ModeType::Server)
292 initType = OC_SERVER;
294 else if (cfg.mode == ModeType::Both)
296 initType = OC_CLIENT_SERVER;
300 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
301 OC_STACK_INVALID_PARAM);
304 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
306 if(OC_STACK_OK != result)
308 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
312 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
315 void InProcServerWrapper::processFunc()
317 auto cLock = m_csdkLock.lock();
318 while(cLock && m_threadRun)
320 OCStackResult result;
323 std::lock_guard<std::recursive_mutex> lock(*cLock);
324 result = OCProcess();
327 // ...the value of variable result is simply ignored for now.
328 if(OC_STACK_ERROR == result)
331 std::this_thread::sleep_for(std::chrono::milliseconds(10));
335 OCStackResult InProcServerWrapper::registerResource(
336 OCResourceHandle& resourceHandle,
337 std::string& resourceURI,
338 const std::string& resourceTypeName,
339 const std::string& resourceInterface,
340 EntityHandler& eHandler,
341 uint8_t resourceProperties)
344 OCStackResult result = OC_STACK_ERROR;
346 auto cLock = m_csdkLock.lock();
350 std::lock_guard<std::recursive_mutex> lock(*cLock);
354 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
355 resourceTypeName.c_str(), // const char * resourceTypeName
356 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
357 resourceURI.c_str(), // const char * uri
358 EntityHandlerWrapper, // OCEntityHandler entityHandler
359 resourceProperties // uint8_t resourceProperties
364 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
365 resourceTypeName.c_str(), // const char * resourceTypeName
366 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
367 resourceURI.c_str(), // const char * uri
368 NULL, // OCEntityHandler entityHandler
369 resourceProperties // uint8_t resourceProperties
373 if(result != OC_STACK_OK)
375 resourceHandle = (OCResourceHandle) 0;
379 entityHandlerMap[resourceHandle] = eHandler;
380 resourceUriMap[resourceHandle] = resourceURI;
385 result = OC_STACK_ERROR;
391 OCStackResult InProcServerWrapper::registerResourceWithHost(
392 OCResourceHandle& resourceHandle,
393 std::string& resourceHOST,
394 std::string& resourceURI,
395 const std::string& resourceTypeName,
396 const std::string& resourceInterface,
397 EntityHandler& eHandler,
398 uint8_t resourceProperties)
401 OCStackResult result = OC_STACK_ERROR;
403 auto cLock = m_csdkLock.lock();
407 std::lock_guard < std::recursive_mutex > lock(*cLock);
409 if (NULL != eHandler)
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 resourceURI.c_str(), // const char * uri
416 EntityHandlerWrapper, // OCEntityHandler entityHandler
417 resourceProperties // uint8_t resourceProperties
422 result = OCCreateResourceWithHost(&resourceHandle, // OCResourceHandle *handle
423 resourceTypeName.c_str(), // const char * resourceTypeName
424 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix
425 resourceHOST.c_str(), // const char * host
426 resourceURI.c_str(), // const char * uri
427 nullptr, // OCEntityHandler entityHandler
428 resourceProperties // uint8_t resourceProperties
432 if (result != OC_STACK_OK)
434 resourceHandle = nullptr;
438 entityHandlerMap[resourceHandle] = eHandler;
439 resourceUriMap[resourceHandle] = resourceURI;
444 result = OC_STACK_ERROR;
449 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
450 (EntityHandler entityHandler)
452 OCStackResult result = OC_STACK_ERROR;
454 defaultDeviceEntityHandler = entityHandler;
458 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
462 // If Null passed we unset
463 result = OCSetDefaultDeviceEntityHandler(NULL);
469 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
471 auto cLock = m_csdkLock.lock();
472 OCStackResult result = OC_STACK_ERROR;
476 std::lock_guard<std::recursive_mutex> lock(*cLock);
477 result = OCDeleteResource(resourceHandle);
479 if(result == OC_STACK_OK)
481 resourceUriMap.erase(resourceHandle);
485 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
490 result = OC_STACK_ERROR;
496 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
497 const std::string& resourceTypeName)
499 auto cLock = m_csdkLock.lock();
500 OCStackResult result;
503 std::lock_guard<std::recursive_mutex> lock(*cLock);
504 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
508 result = OC_STACK_ERROR;
511 if (result != OC_STACK_OK)
513 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
518 OCStackResult InProcServerWrapper::bindInterfaceToResource(
519 const OCResourceHandle& resourceHandle,
520 const std::string& resourceInterfaceName)
522 auto cLock = m_csdkLock.lock();
523 OCStackResult result;
526 std::lock_guard<std::recursive_mutex> lock(*cLock);
527 result = OCBindResourceInterfaceToResource(resourceHandle,
528 resourceInterfaceName.c_str());
532 result = OC_STACK_ERROR;
535 if (result != OC_STACK_OK)
537 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
542 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
544 auto cLock = m_csdkLock.lock();
545 OCStackResult result = OC_STACK_ERROR;
548 std::lock_guard<std::recursive_mutex> lock(*cLock);
549 result = OCStartPresence(seconds);
552 if(result != OC_STACK_OK)
554 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
559 OCStackResult InProcServerWrapper::stopPresence()
561 auto cLock = m_csdkLock.lock();
562 OCStackResult result = OC_STACK_ERROR;
565 std::lock_guard<std::recursive_mutex> lock(*cLock);
566 result = OCStopPresence();
569 if(result != OC_STACK_OK)
571 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
576 InProcServerWrapper::~InProcServerWrapper()
578 if(m_processThread.joinable())
581 m_processThread.join();