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);
64 if(flag & OC_REQUEST_FLAG)
66 pRequest->setRequestHandlerFlag(OC::RequestHandlerFlag::RequestFlag);
68 if(entityHandlerRequest)
70 if(entityHandlerRequest->query)
72 OC::Utilities::QueryParamsKeyVal qp = OC::Utilities::getQueryParams(
73 entityHandlerRequest->query);
77 pRequest->setQueryParams(qp);
80 if(entityHandlerRequest->numRcvdVendorSpecificHeaderOptions != 0)
82 //Set the header options here.
84 std::string optionData;
85 HeaderOptions headerOptions;
88 i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions;
91 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
92 optionData = reinterpret_cast<const char*>
93 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
94 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
95 headerOptions.push_back(headerOption);
97 pRequest->setHeaderOptions(headerOptions);
100 if(OC_REST_GET == entityHandlerRequest->method)
102 pRequest->setRequestType(OC::PlatformCommands::GET);
104 else if(OC_REST_PUT == entityHandlerRequest->method)
106 pRequest->setRequestType(OC::PlatformCommands::PUT);
107 pRequest->setPayload(entityHandlerRequest->payload);
109 else if(OC_REST_POST == entityHandlerRequest->method)
111 pRequest->setRequestType(OC::PlatformCommands::POST);
112 pRequest->setPayload(entityHandlerRequest->payload);
114 else if(OC_REST_DELETE == entityHandlerRequest->method)
116 pRequest->setRequestType(OC::PlatformCommands::DELETE);
121 if(flag & OC_OBSERVE_FLAG)
123 pRequest->setRequestHandlerFlag(
124 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
126 if(entityHandlerRequest)
128 OC::ObservationInfo observationInfo;
129 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo.action;
130 observationInfo.obsId = entityHandlerRequest->obsInfo.obsId;
132 observationInfo.connectivityType = static_cast<OCConnectivityType>(
133 (entityHandlerRequest->devAddr.adapter << CT_ADAPTER_SHIFT) |
134 (entityHandlerRequest->devAddr.flags & CT_MASK_FLAGS));
135 observationInfo.address = entityHandlerRequest->devAddr.addr;
136 observationInfo.port = entityHandlerRequest->devAddr.port;
137 pRequest->setObservationInfo(observationInfo);
142 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
143 OCEntityHandlerRequest * entityHandlerRequest,
145 void * /*callbackParam*/)
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,
185 void* /*callbackParam*/)
187 OCEntityHandlerResult result = OC_EH_ERROR;
189 oclog() << "\nIn entity handler wrapper: " << endl;
191 if(NULL == entityHandlerRequest)
193 oclog() << "Entity handler request is NULL." << endl;
197 auto pRequest = std::make_shared<OC::OCResourceRequest>();
199 formResourceRequest(flag, entityHandlerRequest, pRequest);
201 std::map <OCResourceHandle, std::string>::iterator resourceUriEntry;
202 std::map <OCResourceHandle, std::string>::iterator resourceUriEnd;
204 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
205 resourceUriEntry = OC::details::resourceUriMap.find(entityHandlerRequest->resource);
206 resourceUriEnd = OC::details::resourceUriMap.end();
208 // Finding the corresponding URI for a resource handle and set the URI in the request
209 if(resourceUriEntry != resourceUriEnd)
211 pRequest->setResourceUri(resourceUriEntry->second);
215 oclog() << "Resource handle not found; Resource URI not set in request";
219 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEntry;
220 std::map <OCResourceHandle, OC::EntityHandler>::iterator entityHandlerEnd;
222 // Finding the corresponding CPP Application entityHandler for a given resource
223 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
224 entityHandlerEntry = OC::details::entityHandlerMap.find(entityHandlerRequest->resource);
225 entityHandlerEnd = OC::details::entityHandlerMap.end();
228 if(entityHandlerEntry != entityHandlerEnd)
230 // Call CPP Application Entity Handler
231 if(entityHandlerEntry->second)
233 result = entityHandlerEntry->second(pRequest);
237 oclog() << "C stack should not call again for parent resource\n";
243 oclog() << "No entity handler found." << endl;
252 InProcServerWrapper::InProcServerWrapper(
253 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
254 : m_csdkLock(csdkLock)
258 if(cfg.mode == ModeType::Server)
260 initType = OC_SERVER;
262 else if (cfg.mode == ModeType::Both)
264 initType = OC_CLIENT_SERVER;
266 else if (cfg.mode == ModeType::Gateway)
268 initType = OC_GATEWAY;
272 throw InitializeException(OC::InitException::NOT_CONFIGURED_AS_SERVER,
273 OC_STACK_INVALID_PARAM);
276 OCTransportFlags serverFlags =
277 static_cast<OCTransportFlags>(cfg.serverConnectivity & CT_MASK_FLAGS);
278 OCTransportFlags clientFlags =
279 static_cast<OCTransportFlags>(cfg.clientConnectivity & CT_MASK_FLAGS);
280 OCStackResult result = OCInit1(initType, serverFlags, clientFlags);
282 if(OC_STACK_OK != result)
284 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
288 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
291 void InProcServerWrapper::processFunc()
293 auto cLock = m_csdkLock.lock();
294 while(cLock && m_threadRun)
296 OCStackResult result;
299 std::lock_guard<std::recursive_mutex> lock(*cLock);
300 result = OCProcess();
303 if(OC_STACK_ERROR == result)
305 oclog() << "OCProcess failed with result " << result <<std::flush;
306 // ...the value of variable result is simply ignored for now.
309 std::this_thread::sleep_for(std::chrono::milliseconds(10));
313 OCStackResult InProcServerWrapper::registerDeviceInfo(const OCDeviceInfo deviceInfo)
315 auto cLock = m_csdkLock.lock();
316 OCStackResult result = OC_STACK_ERROR;
319 std::lock_guard<std::recursive_mutex> lock(*cLock);
320 result = OCSetDeviceInfo(deviceInfo);
325 OCStackResult InProcServerWrapper::registerPlatformInfo(const OCPlatformInfo platformInfo)
327 auto cLock = m_csdkLock.lock();
328 OCStackResult result = OC_STACK_ERROR;
331 std::lock_guard<std::recursive_mutex> lock(*cLock);
332 result = OCSetPlatformInfo(platformInfo);
337 OCStackResult InProcServerWrapper::registerResource(
338 OCResourceHandle& resourceHandle,
339 std::string& resourceURI,
340 const std::string& resourceTypeName,
341 const std::string& resourceInterface,
342 EntityHandler& eHandler,
343 uint8_t resourceProperties)
346 OCStackResult result = OC_STACK_ERROR;
348 auto cLock = m_csdkLock.lock();
352 std::lock_guard<std::recursive_mutex> lock(*cLock);
356 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
357 resourceTypeName.c_str(), // const char * resourceTypeName
358 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
359 resourceURI.c_str(), // const char * uri
360 EntityHandlerWrapper, // OCEntityHandler entityHandler
362 resourceProperties // uint8_t resourceProperties
367 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
368 resourceTypeName.c_str(), // const char * resourceTypeName
369 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
370 resourceURI.c_str(), // const char * uri
371 NULL, // OCEntityHandler entityHandler
373 resourceProperties // uint8_t resourceProperties
377 if(result != OC_STACK_OK)
379 resourceHandle = (OCResourceHandle) 0;
383 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
384 OC::details::entityHandlerMap[resourceHandle] = eHandler;
385 OC::details::resourceUriMap[resourceHandle] = resourceURI;
390 result = OC_STACK_ERROR;
398 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
399 (EntityHandler entityHandler)
401 OCStackResult result = OC_STACK_ERROR;
404 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
405 OC::details::defaultDeviceEntityHandler = entityHandler;
410 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper, NULL);
414 // If Null passed we unset
415 result = OCSetDefaultDeviceEntityHandler(NULL, 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 std::lock_guard<std::mutex> lock(OC::details::serverWrapperLock);
434 OC::details::resourceUriMap.erase(resourceHandle);
438 throw OCException(OC::Exception::RESOURCE_UNREG_FAILED, result);
443 result = OC_STACK_ERROR;
449 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
450 const std::string& resourceTypeName)
452 auto cLock = m_csdkLock.lock();
453 OCStackResult result;
456 std::lock_guard<std::recursive_mutex> lock(*cLock);
457 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
461 result = OC_STACK_ERROR;
464 if (result != OC_STACK_OK)
466 throw OCException(OC::Exception::BIND_TYPE_FAILED, result);
471 OCStackResult InProcServerWrapper::bindInterfaceToResource(
472 const OCResourceHandle& resourceHandle,
473 const std::string& resourceInterfaceName)
475 auto cLock = m_csdkLock.lock();
476 OCStackResult result;
479 std::lock_guard<std::recursive_mutex> lock(*cLock);
480 result = OCBindResourceInterfaceToResource(resourceHandle,
481 resourceInterfaceName.c_str());
485 result = OC_STACK_ERROR;
488 if (result != OC_STACK_OK)
490 throw OCException(OC::Exception::BIND_INTERFACE_FAILED, result);
495 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
497 auto cLock = m_csdkLock.lock();
498 OCStackResult result = OC_STACK_ERROR;
501 std::lock_guard<std::recursive_mutex> lock(*cLock);
502 result = OCStartPresence(seconds);
505 if(result != OC_STACK_OK)
507 throw OCException(OC::Exception::START_PRESENCE_FAILED, result);
512 OCStackResult InProcServerWrapper::stopPresence()
514 auto cLock = m_csdkLock.lock();
515 OCStackResult result = OC_STACK_ERROR;
518 std::lock_guard<std::recursive_mutex> lock(*cLock);
519 result = OCStopPresence();
522 if(result != OC_STACK_OK)
524 throw OCException(OC::Exception::END_PRESENCE_FAILED, result);
529 OCStackResult InProcServerWrapper::sendResponse(
530 const std::shared_ptr<OCResourceResponse> pResponse)
532 auto cLock = m_csdkLock.lock();
533 OCStackResult result = OC_STACK_ERROR;
537 result = OC_STACK_MALFORMED_RESPONSE;
538 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_MALFORMED_RESPONSE);
542 OCEntityHandlerResponse response;
543 // OCRepPayload* payLoad = pResponse->getPayload();
544 HeaderOptions serverHeaderOptions = pResponse->getHeaderOptions();
546 response.requestHandle = pResponse->getRequestHandle();
547 response.resourceHandle = pResponse->getResourceHandle();
548 response.ehResult = pResponse->getResponseResult();
550 response.payload = reinterpret_cast<OCPayload*>(pResponse->getPayload());
552 response.persistentBufferFlag = 0;
554 response.numSendVendorSpecificHeaderOptions = serverHeaderOptions.size();
556 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
558 response.sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
559 response.sendVendorSpecificHeaderOptions[i].optionID =
560 static_cast<uint16_t>(it->getOptionID());
561 response.sendVendorSpecificHeaderOptions[i].optionLength =
562 (it->getOptionData()).length() + 1;
563 std::string optionData = it->getOptionData();
564 std::copy(optionData.begin(),
566 response.sendVendorSpecificHeaderOptions[i].optionData);
567 response.sendVendorSpecificHeaderOptions[i].optionData[it->getOptionData().length()]
572 if(OC_EH_RESOURCE_CREATED == response.ehResult)
574 pResponse->getNewResourceUri().copy(response.resourceUri,
575 sizeof (response.resourceUri) - 1);
576 response.resourceUri[pResponse->getNewResourceUri().length()] = '\0';
581 std::lock_guard<std::recursive_mutex> lock(*cLock);
582 result = OCDoResponse(&response);
586 OICFree(response.payload);
587 result = OC_STACK_ERROR;
590 if(result != OC_STACK_OK)
592 oclog() << "Error sending response\n";
598 InProcServerWrapper::~InProcServerWrapper()
600 if(m_processThread.joinable())
603 m_processThread.join();