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 <oic_malloc.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);
62 pRequest->setMessageID(entityHandlerRequest->messageID);
65 if(flag & OC_REQUEST_FLAG)
67 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
69 if(entityHandlerRequest)
71 if(entityHandlerRequest->query)
73 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
74 entityHandlerRequest->query);
78 pRequest->setQueryParams(qp);
81 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
83 //Set the header options here.
85 std::string optionData;
86 HeaderOptions headerOptions;
89 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
92 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
93 optionData = reinterpret_cast<const char*>
94 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
95 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
96 headerOptions.push_back(headerOption);
98 pRequest->setHeaderOptions(headerOptions);
101 if(OC_REST_GET == entityHandlerRequest->method)
103 pRequest->setRequestType(OC::PlatformCommands::GET);
105 else if(OC_REST_PUT == entityHandlerRequest->method)
107 pRequest->setRequestType(OC::PlatformCommands::PUT);
108 pRequest->setPayload(entityHandlerRequest->payload);
110 else if(OC_REST_POST == entityHandlerRequest->method)
112 pRequest->setRequestType(OC::PlatformCommands::POST);
113 pRequest->setPayload(entityHandlerRequest->payload);
115 else if(OC_REST_DELETE == entityHandlerRequest->method)
117 pRequest->setRequestType(OC::PlatformCommands::DELETE);
122 if(flag & OC_OBSERVE_FLAG)
124 pRequest->setRequestHandlerFlag(
125 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
127 if(entityHandlerRequest)
129 OC::ObservationInfo observationInfo;
130 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
131 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
133 observationInfo.connectivityType = static_cast<OCConnectivityType>(
134 (entityHandlerRequest->devAddr.adapter << CT_ADAPTER_SHIFT) |
135 (entityHandlerRequest->devAddr.flags & CT_MASK_FLAGS));
136 observationInfo.address = entityHandlerRequest->devAddr.addr;
137 observationInfo.port = entityHandlerRequest->devAddr.port;
138 pRequest->setObservationInfo(observationInfo);
143 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
144 OCEntityHandlerRequest * entityHandlerRequest,
146 void * /*callbackParam*/)
148 OCEntityHandlerResult result = OC_EH_ERROR;
150 OC::oclog() << "In Default device entity handler wrapper";
152 if(NULL == entityHandlerRequest)
154 oclog() << "Entity handler request is NULL.";
158 auto pRequest = std::make_shared<OC::OCResourceRequest>();
160 formResourceRequest(flag, entityHandlerRequest, pRequest);
162 pRequest->setResourceUri(std::string(uri));
164 EntityHandler defHandler;
166 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
167 defHandler = OC::details::defaultDeviceEntityHandler;
172 result = defHandler(pRequest);
176 oclog() << "Default device entity handler was not set.";
184 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
185 OCEntityHandlerRequest * entityHandlerRequest,
186 void* /*callbackParam*/)
188 OCEntityHandlerResult result = OC_EH_ERROR;
190 oclog() << "\nIn entity handler wrapper: " << endl;
192 if(NULL == entityHandlerRequest)
194 oclog() << "Entity handler request is NULL." << endl;
198 auto pRequest = std::make_shared<OC::OCResourceRequest>();
200 formResourceRequest(flag, entityHandlerRequest, pRequest);
202 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
203 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
205 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
206 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
207 resourceUriEnd = OC::details::resourceUriMap.end();
209 // Finding the corresponding URI for a resource handle and set the URI in the request
210 if(resourceUriEntry != resourceUriEnd)
212 pRequest->setResourceUri(resourceUriEntry->second);
216 oclog() << "Resource handle not found; Resource URI not set in request";
220 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
221 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
223 // Finding the corresponding CPP Application entityHandler for a given resource
224 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
225 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
226 entityHandlerEnd = OC::details::entityHandlerMap.end();
229 if(entityHandlerEntry != entityHandlerEnd)
231 // Call CPP Application Entity Handler
232 if(entityHandlerEntry->second)
234 result = entityHandlerEntry->second(pRequest);
238 oclog() << "C stack should not call again for parent resource\n";
244 oclog() << "No entity handler found." << endl;
253 InProcServerWrapper::InProcServerWrapper(
254 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
255 : m_csdkLock(csdkLock)
259 if(cfg.mode == ModeType::Server)
261 initType = OC_SERVER;
263 else if (cfg.mode == ModeType::Both)
265 initType = OC_CLIENT_SERVER;
267 else if (cfg.mode == ModeType::Gateway)
269 initType = OC_GATEWAY;
273 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
274 OC_STACK_INVALID_PARAM);
277 OCTransportFlags serverFlags =
278 static_cast<OCTransportFlags>(cfg.serverConnectivity & CT_MASK_FLAGS);
279 OCTransportFlags clientFlags =
280 static_cast<OCTransportFlags>(cfg.clientConnectivity & CT_MASK_FLAGS);
281 OCStackResult result = OCInit1(initType, serverFlags, clientFlags);
283 if(OC_STACK_OK != result)
285 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
289 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
292 void InProcServerWrapper::processFunc()
294 auto cLock = m_csdkLock.lock();
295 while(cLock && m_threadRun)
297 OCStackResult result;
300 std::lock_guard<std::recursive_mutex> lock(*cLock);
301 result = OCProcess();
304 if(OC_STACK_ERROR == result)
306 oclog() << "OCProcess failed with result " << result <<std::flush;
307 // ...the value of variable result is simply ignored for now.
310 std::this_thread::sleep_for(std::chrono::milliseconds(10));
314 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
316 auto cLock = m_csdkLock.lock();
317 OCStackResult result = OC_STACK_ERROR;
320 std::lock_guard<std::recursive_mutex> lock(*cLock);
321 result = OCSetDeviceInfo(deviceInfo);
326 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
328 auto cLock = m_csdkLock.lock();
329 OCStackResult result = OC_STACK_ERROR;
332 std::lock_guard<std::recursive_mutex> lock(*cLock);
333 result = OCSetPlatformInfo(platformInfo);
338 OCStackResult InProcServerWrapper::registerResource(
339 OCResourceHandle& resourceHandle,
340 std::string& resourceURI,
341 const std::string& resourceTypeName,
342 const std::string& resourceInterface,
343 EntityHandler& eHandler,
344 uint8_t resourceProperties)
347 OCStackResult result = OC_STACK_ERROR;
349 auto cLock = m_csdkLock.lock();
353 std::lock_guard<std::recursive_mutex> lock(*cLock);
357 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
358 resourceTypeName.c_str(), // const char * resourceTypeName
359 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
360 resourceURI.c_str(), // const char * uri
361 EntityHandlerWrapper, // OCEntityHandler entityHandler
363 resourceProperties // uint8_t resourceProperties
368 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
369 resourceTypeName.c_str(), // const char * resourceTypeName
370 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
371 resourceURI.c_str(), // const char * uri
372 NULL, // OCEntityHandler entityHandler
374 resourceProperties // uint8_t resourceProperties
378 if(result != OC_STACK_OK)
380 resourceHandle = (OCResourceHandle) 0;
384 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
385 OC::details::entityHandlerMap[resourceHandle] = eHandler;
386 OC::details::resourceUriMap[resourceHandle] = resourceURI;
391 result = OC_STACK_ERROR;
399 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
400 (EntityHandler entityHandler)
402 OCStackResult result = OC_STACK_ERROR;
405 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
406 OC::details::defaultDeviceEntityHandler = entityHandler;
411 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
415 // If Null passed we unset
416 result = OCSetDefaultDeviceEntityHandler(NULL, NULL);
422 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
424 auto cLock = m_csdkLock.lock();
425 OCStackResult result = OC_STACK_ERROR;
429 std::lock_guard<std::recursive_mutex> lock(*cLock);
430 result = OCDeleteResource(resourceHandle);
432 if(result == OC_STACK_OK)
434 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
435 OC::details::resourceUriMap.erase(resourceHandle);
439 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
444 result = OC_STACK_ERROR;
450 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
451 const std::string& resourceTypeName)
453 auto cLock = m_csdkLock.lock();
454 OCStackResult result;
457 std::lock_guard<std::recursive_mutex> lock(*cLock);
458 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
462 result = OC_STACK_ERROR;
465 if (result != OC_STACK_OK)
467 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
472 OCStackResult InProcServerWrapper::bindInterfaceToResource(
473 const OCResourceHandle& resourceHandle,
474 const std::string& resourceInterfaceName)
476 auto cLock = m_csdkLock.lock();
477 OCStackResult result;
480 std::lock_guard<std::recursive_mutex> lock(*cLock);
481 result = OCBindResourceInterfaceToResource(resourceHandle,
482 resourceInterfaceName.c_str());
486 result = OC_STACK_ERROR;
489 if (result != OC_STACK_OK)
491 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
496 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
498 auto cLock = m_csdkLock.lock();
499 OCStackResult result = OC_STACK_ERROR;
502 std::lock_guard<std::recursive_mutex> lock(*cLock);
503 result = OCStartPresence(seconds);
506 if(result != OC_STACK_OK)
508 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
513 OCStackResult InProcServerWrapper::stopPresence()
515 auto cLock = m_csdkLock.lock();
516 OCStackResult result = OC_STACK_ERROR;
519 std::lock_guard<std::recursive_mutex> lock(*cLock);
520 result = OCStopPresence();
523 if(result != OC_STACK_OK)
525 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
530 OCStackResult InProcServerWrapper::sendResponse(
531 const std::shared_ptr<OCResourceResponse> pResponse)
533 auto cLock = m_csdkLock.lock();
534 OCStackResult result = OC_STACK_ERROR;
538 result = OC_STACK_MALFORMED_RESPONSE;
539 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
543 OCEntityHandlerResponse response;
544 // OCRepPayload* payLoad = pResponse->getPayload();
545 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
547 response.requestHandle = pResponse->getRequestHandle();
548 response.resourceHandle = pResponse->getResourceHandle();
549 response.ehResult = pResponse->getResponseResult();
551 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
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 std::string optionData = it->getOptionData();
565 std::copy(optionData.begin(),
567 response.sendVendorSpecificHeaderOptions[i].optionData);
568 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
573 if(OC_EH_RESOURCE_CREATED == response.ehResult)
575 pResponse->getNewResourceUri().copy(response.resourceUri,
576 sizeof (response.resourceUri) - 1);
577 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
582 std::lock_guard<std::recursive_mutex> lock(*cLock);
583 result = OCDoResponse(&response);
587 OICFree(response.payload);
588 result = OC_STACK_ERROR;
591 if(result != OC_STACK_OK)
593 oclog() << "Error sending response\n";
599 InProcServerWrapper::~InProcServerWrapper()
601 if(m_processThread.joinable())
604 m_processThread.join();