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;
79 for(int i = 0; i < MAX_HEADER_OPTIONS; i++)
81 optionID = entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionID;
82 optionData = reinterpret_cast<const char*>
83 (entityHandlerRequest->rcvdVendorSpecificHeaderOptions[i].optionData);
84 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
85 headerOptions.push_back(headerOption);
87 pRequest->setHeaderOptions(headerOptions);
90 if(OC_REST_GET == entityHandlerRequest->method)
92 // TODO Why strings : "GET"??
93 pRequest->setRequestType("GET");
95 else if(OC_REST_PUT == entityHandlerRequest->method)
97 pRequest->setRequestType("PUT");
98 pRequest->setPayload(std::string(reinterpret_cast<const char*>
99 (entityHandlerRequest->reqJSONPayload)));
101 else if(OC_REST_POST == entityHandlerRequest->method)
103 pRequest->setRequestType("POST");
104 pRequest->setPayload(std::string(reinterpret_cast<const char*>
105 (entityHandlerRequest->reqJSONPayload)));
107 else if(OC_REST_DELETE == entityHandlerRequest->method)
109 pRequest->setRequestType("DELETE");
114 if(flag & OC_OBSERVE_FLAG)
116 pRequest->setRequestHandlerFlag(
117 OC::RequestHandlerFlag::RequestFlag | OC::RequestHandlerFlag::ObserverFlag);
118 if(entityHandlerRequest->obsInfo)
120 OC::ObservationInfo observationInfo;
121 observationInfo.action = (OC::ObserveAction) entityHandlerRequest->obsInfo->action;
122 observationInfo.obsId = entityHandlerRequest->obsInfo->obsId;
123 pRequest->setObservationInfo(observationInfo);
128 void processResourceResponse(OCEntityHandlerFlag flag,
129 OCEntityHandlerRequest * entityHandlerRequest,
130 std::shared_ptr<OCResourceResponse> pResponse)
132 if(flag & OC_REQUEST_FLAG)
134 // TODO we could use const reference
136 HeaderOptions serverHeaderOptions;
140 payLoad = pResponse->getPayload();
141 serverHeaderOptions = pResponse->getHeaderOptions();
145 throw OCException("Response is NULL", OC_STACK_MALFORMED_RESPONSE);
148 if (payLoad.size() < entityHandlerRequest->resJSONPayloadLen)
151 entityHandlerRequest->numSendVendorSpecificHeaderOptions =
152 serverHeaderOptions.size();
153 for (auto it=serverHeaderOptions.begin(); it != serverHeaderOptions.end(); ++it)
155 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].protocolID = OC_COAP_ID;
156 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionID =
157 static_cast<uint16_t>(it->getOptionID());
158 entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionLength =
159 (it->getOptionData()).length() + 1;
160 memcpy(entityHandlerRequest->sendVendorSpecificHeaderOptions[i].optionData,
161 (it->getOptionData()).c_str(),
162 (it->getOptionData()).length() + 1);
166 strncpy((char*)entityHandlerRequest->resJSONPayload,
168 entityHandlerRequest->resJSONPayloadLen);
172 throw OCException("Payload overflow", OC_STACK_MALFORMED_RESPONSE);
178 OCEntityHandlerResult DefaultEntityHandlerWrapper(OCEntityHandlerFlag flag,
179 OCEntityHandlerRequest * entityHandlerRequest,
182 OCEntityHandlerResult result = OC_EH_ERROR;
184 OC::oclog() << "In Default device entity handler wrapper";
186 if(NULL == entityHandlerRequest)
188 oclog() << "Entity handler request is NULL.";
192 auto pRequest = std::make_shared<OC::OCResourceRequest>();
193 auto pResponse = std::make_shared<OC::OCResourceResponse>();
195 formResourceRequest(flag, entityHandlerRequest, pRequest);
197 pRequest->setResourceUri(std::string(uri));
199 if(defaultDeviceEntityHandler)
201 result = defaultDeviceEntityHandler(pRequest, pResponse);
205 oclog() << "Default device entity handler was not set.";
209 processResourceResponse(flag, entityHandlerRequest, pResponse);
215 OCEntityHandlerResult EntityHandlerWrapper(OCEntityHandlerFlag flag,
216 OCEntityHandlerRequest * entityHandlerRequest)
218 OCEntityHandlerResult result = OC_EH_ERROR;
220 oclog() << "\nIn entity handler wrapper: " << endl;
222 if(NULL == entityHandlerRequest)
224 oclog() << "Entity handler request is NULL." << endl;
228 auto pRequest = std::make_shared<OC::OCResourceRequest>();
229 auto pResponse = std::make_shared<OC::OCResourceResponse>();
231 formResourceRequest(flag, entityHandlerRequest, pRequest);
233 // Finding the corresponding URI for a resource handle and set the URI in the request
234 auto resourceUriEntry = resourceUriMap.find(entityHandlerRequest->resource);
235 if(resourceUriEntry != resourceUriMap.end())
237 pRequest->setResourceUri(resourceUriEntry->second);
241 oclog() << "Resource handle not found; Resource URI not set in request";
245 // Finding the corresponding CPP Application entityHandler for a given resource
246 auto entityHandlerEntry = entityHandlerMap.find(entityHandlerRequest->resource);
248 if(entityHandlerEntry != entityHandlerMap.end())
250 // Call CPP Application Entity Handler
251 if(entityHandlerEntry->second)
253 result = entityHandlerEntry->second(pRequest, pResponse);
255 if(OC_EH_RESOURCE_CREATED == result)
257 std::string createdUri = pResponse->getNewResourceUri();
258 strncpy(reinterpret_cast<char*>(entityHandlerRequest->newResourceUri),
260 createdUri.length() + 1);
265 oclog() << "C stack should not call again for parent resource\n";
271 oclog() << "No entity handler found." << endl;
275 processResourceResponse(flag, entityHandlerRequest, pResponse);
282 InProcServerWrapper::InProcServerWrapper(OC::OCPlatform& owner,
283 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
284 : IServerWrapper(owner),
289 if(cfg.mode == ModeType::Server)
291 initType = OC_SERVER;
293 else if (cfg.mode == ModeType::Both)
295 initType = OC_CLIENT_SERVER;
299 throw InitializeException("Cannot construct a Server when configured as a client",
300 OC_STACK_INVALID_PARAM);
303 OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, initType);
305 if(OC_STACK_OK != result)
307 throw InitializeException("Error Initializing Stack", result);
311 m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
314 void InProcServerWrapper::processFunc()
316 auto cLock = m_csdkLock.lock();
317 while(cLock && m_threadRun)
319 OCStackResult result;
322 std::lock_guard<std::recursive_mutex> lock(*cLock);
323 result = OCProcess();
326 // ...the value of variable result is simply ignored for now.
327 if(OC_STACK_ERROR == result)
330 std::this_thread::sleep_for(std::chrono::milliseconds(10));
334 OCStackResult InProcServerWrapper::registerResource(
335 OCResourceHandle& resourceHandle,
336 std::string& resourceURI,
337 const std::string& resourceTypeName,
338 const std::string& resourceInterface,
339 EntityHandler& eHandler,
340 uint8_t resourceProperties)
343 OCStackResult result = OC_STACK_ERROR;
345 auto cLock = m_csdkLock.lock();
349 std::lock_guard<std::recursive_mutex> lock(*cLock);
353 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
354 resourceTypeName.c_str(), // const char * resourceTypeName
355 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
356 resourceURI.c_str(), // const char * uri
357 EntityHandlerWrapper, // OCEntityHandler entityHandler
358 resourceProperties // uint8_t resourceProperties
363 result = OCCreateResource(&resourceHandle, // OCResourceHandle *handle
364 resourceTypeName.c_str(), // const char * resourceTypeName
365 resourceInterface.c_str(), //const char * resourceInterfaceName //TODO fix this
366 resourceURI.c_str(), // const char * uri
367 NULL, // OCEntityHandler entityHandler
368 resourceProperties // uint8_t resourceProperties
372 if(result != OC_STACK_OK)
374 resourceHandle = (OCResourceHandle) 0;
378 entityHandlerMap[resourceHandle] = eHandler;
379 resourceUriMap[resourceHandle] = resourceURI;
384 result = OC_STACK_ERROR;
390 OCStackResult InProcServerWrapper::setDefaultDeviceEntityHandler
391 (EntityHandler entityHandler)
393 OCStackResult result = OC_STACK_ERROR;
395 defaultDeviceEntityHandler = entityHandler;
399 result = OCSetDefaultDeviceEntityHandler(DefaultEntityHandlerWrapper);
403 // If Null passed we unset
404 result = OCSetDefaultDeviceEntityHandler(NULL);
410 OCStackResult InProcServerWrapper::unregisterResource(const OCResourceHandle& resourceHandle)
412 auto cLock = m_csdkLock.lock();
413 OCStackResult result = OC_STACK_ERROR;
417 std::lock_guard<std::recursive_mutex> lock(*cLock);
418 result = OCDeleteResource(resourceHandle);
420 if(result == OC_STACK_OK)
422 resourceUriMap.erase(resourceHandle);
426 throw OCException("Unregistering resource failed", result);
431 result = OC_STACK_ERROR;
437 OCStackResult InProcServerWrapper::bindTypeToResource(const OCResourceHandle& resourceHandle,
438 const std::string& resourceTypeName)
440 auto cLock = m_csdkLock.lock();
441 OCStackResult result;
444 std::lock_guard<std::recursive_mutex> lock(*cLock);
445 result = OCBindResourceTypeToResource(resourceHandle, resourceTypeName.c_str());
449 result = OC_STACK_ERROR;
452 if (result != OC_STACK_OK)
454 throw OCException("Bind Type to resource failed", result);
459 OCStackResult InProcServerWrapper::bindInterfaceToResource(
460 const OCResourceHandle& resourceHandle,
461 const std::string& resourceInterfaceName)
463 auto cLock = m_csdkLock.lock();
464 OCStackResult result;
467 std::lock_guard<std::recursive_mutex> lock(*cLock);
468 result = OCBindResourceInterfaceToResource(resourceHandle,
469 resourceInterfaceName.c_str());
473 result = OC_STACK_ERROR;
476 if (result != OC_STACK_OK)
478 throw OCException("Bind Interface to resource failed", result);
483 OCStackResult InProcServerWrapper::startPresence(const unsigned int seconds)
485 auto cLock = m_csdkLock.lock();
486 OCStackResult result = OC_STACK_ERROR;
489 std::lock_guard<std::recursive_mutex> lock(*cLock);
490 result = OCStartPresence(seconds);
493 if(result != OC_STACK_OK)
495 throw OCException("startPresence failed", result);
500 OCStackResult InProcServerWrapper::stopPresence()
502 auto cLock = m_csdkLock.lock();
503 OCStackResult result = OC_STACK_ERROR;
506 std::lock_guard<std::recursive_mutex> lock(*cLock);
507 result = OCStopPresence();
510 if(result != OC_STACK_OK)
512 throw OCException("stopPresence failed", result);
517 InProcServerWrapper::~InProcServerWrapper()
519 if(m_processThread.joinable())
522 m_processThread.join();