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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "InProcClientWrapper.h"
24 #include "OCPlatform.h"
25 #include "OCResource.h"
26 #include "ocpayload.h"
27 #include <OCSerialization.h>
32 InProcClientWrapper::InProcClientWrapper(
33 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
34 : m_threadRun(false), m_csdkLock(csdkLock),
37 // if the config type is server, we ought to never get called. If the config type
38 // is both, we count on the server to run the thread and do the initialize
40 if (m_cfg.mode == ModeType::Client)
42 OCTransportFlags serverFlags =
43 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
44 OCTransportFlags clientFlags =
45 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
46 OCStackResult result = OCInit1(OC_CLIENT, serverFlags, clientFlags);
48 if (OC_STACK_OK != result)
50 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
54 m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
58 InProcClientWrapper::~InProcClientWrapper()
60 if (m_threadRun && m_listeningThread.joinable())
63 m_listeningThread.join();
66 // only stop if we are the ones who actually called 'init'. We are counting
67 // on the server to do the stop.
68 if (m_cfg.mode == ModeType::Client)
74 void InProcClientWrapper::listeningFunc()
79 auto cLock = m_csdkLock.lock();
82 std::lock_guard<std::recursive_mutex> lock(*cLock);
87 result = OC_STACK_ERROR;
90 if (result != OC_STACK_OK)
92 // TODO: do something with result if failed?
95 // To minimize CPU utilization we may wish to do this with sleep
96 std::this_thread::sleep_for(std::chrono::milliseconds(10));
100 OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
102 if (clientResponse->payload == nullptr ||
104 clientResponse->payload->type != PAYLOAD_TYPE_DEVICE &&
105 clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM &&
106 clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
110 //OCPayloadDestroy(clientResponse->payload);
111 return OCRepresentation();
115 oc.setPayload(clientResponse->payload);
116 //OCPayloadDestroy(clientResponse->payload);
118 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
119 if (it == oc.representations().end())
121 return OCRepresentation();
124 // first one is considered the root, everything else is considered a child of this one.
125 OCRepresentation root = *it;
126 root.setDevAddr(clientResponse->devAddr);
127 root.setUri(clientResponse->resourceUri);
130 std::for_each(it, oc.representations().end(),
131 [&root](const OCRepresentation& repItr)
132 {root.addChild(repItr);});
137 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
138 OCClientResponse* clientResponse)
140 ClientCallbackContext::ListenContext* context =
141 static_cast<ClientCallbackContext::ListenContext*>(ctx);
143 if (clientResponse->result != OC_STACK_OK)
145 oclog() << "listenCallback(): failed to create resource. clientResponse: "
146 << clientResponse->result
149 return OC_STACK_KEEP_TRANSACTION;
152 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
154 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
156 return OC_STACK_KEEP_TRANSACTION;
159 auto clientWrapper = context->clientWrapper.lock();
163 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
165 return OC_STACK_KEEP_TRANSACTION;
170 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
171 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
172 // loop to ensure valid construction of all resources
174 for(auto resource : container.Resources())
176 std::thread exec(context->callback, resource);
180 catch (std::exception &e)
182 oclog() << "Exception in listCallback, ignoring response: "
183 << e.what() << std::flush;
187 return OC_STACK_KEEP_TRANSACTION;
190 OCStackApplicationResult listenErrorCallback(void* ctx, OCDoHandle /*handle*/,
191 OCClientResponse* clientResponse)
193 if (!ctx || !clientResponse)
195 return OC_STACK_KEEP_TRANSACTION;
198 ClientCallbackContext::ListenErrorContext* context =
199 static_cast<ClientCallbackContext::ListenErrorContext*>(ctx);
202 return OC_STACK_KEEP_TRANSACTION;
205 OCStackResult result = clientResponse->result;
206 if (result == OC_STACK_OK)
208 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
210 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
212 return OC_STACK_KEEP_TRANSACTION;
215 auto clientWrapper = context->clientWrapper.lock();
219 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
221 return OC_STACK_KEEP_TRANSACTION;
224 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
225 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
226 // loop to ensure valid construction of all resources
227 for (auto resource : container.Resources())
229 std::thread exec(context->callback, resource);
232 return OC_STACK_KEEP_TRANSACTION;
235 std::string resourceURI = clientResponse->resourceUri;
236 std::thread exec(context->errorCallback, resourceURI, result);
238 return OC_STACK_KEEP_TRANSACTION;
241 OCStackResult InProcClientWrapper::ListenForResource(
242 const std::string& serviceUrl,
243 const std::string& resourceType,
244 OCConnectivityType connectivityType,
245 FindCallback& callback, QualityOfService QoS)
249 return OC_STACK_INVALID_PARAM;
252 OCStackResult result;
253 ostringstream resourceUri;
254 resourceUri << serviceUrl << resourceType;
256 ClientCallbackContext::ListenContext* context =
257 new ClientCallbackContext::ListenContext(callback, shared_from_this());
258 OCCallbackData cbdata;
259 cbdata.context = static_cast<void*>(context),
260 cbdata.cb = listenCallback;
261 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
263 auto cLock = m_csdkLock.lock();
266 std::lock_guard<std::recursive_mutex> lock(*cLock);
267 result = OCDoResource(nullptr, OC_REST_DISCOVER,
268 resourceUri.str().c_str(),
269 nullptr, nullptr, connectivityType,
270 static_cast<OCQualityOfService>(QoS),
277 result = OC_STACK_ERROR;
282 OCStackResult InProcClientWrapper::ListenErrorForResource(
283 const std::string& serviceUrl,
284 const std::string& resourceType,
285 OCConnectivityType connectivityType,
286 FindCallback& callback, FindErrorCallback& errorCallback,
287 QualityOfService QoS)
291 return OC_STACK_INVALID_PARAM;
294 ostringstream resourceUri;
295 resourceUri << serviceUrl << resourceType;
297 ClientCallbackContext::ListenErrorContext* context =
298 new ClientCallbackContext::ListenErrorContext(callback, errorCallback,
302 return OC_STACK_ERROR;
305 OCCallbackData cbdata(
306 static_cast<void*>(context),
308 [](void* c){delete static_cast<ClientCallbackContext::ListenErrorContext*>(c);}
311 OCStackResult result;
312 auto cLock = m_csdkLock.lock();
315 std::lock_guard<std::recursive_mutex> lock(*cLock);
316 result = OCDoResource(nullptr, OC_REST_DISCOVER,
317 resourceUri.str().c_str(),
318 nullptr, nullptr, connectivityType,
319 static_cast<OCQualityOfService>(QoS),
326 result = OC_STACK_ERROR;
331 OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
332 OCClientResponse* clientResponse)
334 ClientCallbackContext::MQTopicContext* context =
335 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
337 if (!clientResponse || !context)
339 return OC_STACK_DELETE_TRANSACTION;
342 std::string resourceURI = clientResponse->resourceUri;
343 if (clientResponse->result != OC_STACK_OK)
345 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
346 << clientResponse->result
349 std::thread exec(context->callback, clientResponse->result,
350 resourceURI, nullptr);
353 return OC_STACK_DELETE_TRANSACTION;
356 auto clientWrapper = context->clientWrapper.lock();
359 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
361 return OC_STACK_DELETE_TRANSACTION;
366 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
367 (OCRepPayload *) clientResponse->payload);
369 // loop to ensure valid construction of all resources
370 for (auto resource : container.Resources())
372 std::thread exec(context->callback, clientResponse->result,
373 resourceURI, resource);
377 catch (std::exception &e)
379 oclog() << "Exception in listCallback, ignoring response: "
380 << e.what() << std::flush;
383 return OC_STACK_DELETE_TRANSACTION;
386 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
387 const std::string& resourceUri,
388 const QueryParamsMap& queryParams,
389 const HeaderOptions& headerOptions,
390 MQTopicCallback& callback,
391 QualityOfService QoS)
393 oclog() << "ListenForMQTopic()" << std::flush;
397 return OC_STACK_INVALID_PARAM;
400 ClientCallbackContext::MQTopicContext* context =
401 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
402 OCCallbackData cbdata;
403 cbdata.context = static_cast<void*>(context),
404 cbdata.cb = listenMQCallback;
405 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
407 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
409 OCStackResult result = OC_STACK_ERROR;
410 auto cLock = m_csdkLock.lock();
413 std::lock_guard<std::recursive_mutex> lock(*cLock);
414 OCHeaderOption options[MAX_HEADER_OPTIONS];
415 result = OCDoResource(
416 nullptr, OC_REST_GET,
420 static_cast<OCQualityOfService>(QoS),
422 assembleHeaderOptions(options, headerOptions),
423 headerOptions.size());
434 OCStackApplicationResult listenDeviceCallback(void* ctx,
435 OCDoHandle /*handle*/,
436 OCClientResponse* clientResponse)
438 ClientCallbackContext::DeviceListenContext* context =
439 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
443 OCRepresentation rep = parseGetSetCallback(clientResponse);
444 std::thread exec(context->callback, rep);
447 catch(OC::OCException& e)
449 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
450 <<e.what() <<std::flush;
453 return OC_STACK_KEEP_TRANSACTION;
456 OCStackResult InProcClientWrapper::ListenForDevice(
457 const std::string& serviceUrl,
458 const std::string& deviceURI,
459 OCConnectivityType connectivityType,
460 FindDeviceCallback& callback,
461 QualityOfService QoS)
465 return OC_STACK_INVALID_PARAM;
467 OCStackResult result;
468 ostringstream deviceUri;
469 deviceUri << serviceUrl << deviceURI;
471 ClientCallbackContext::DeviceListenContext* context =
472 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
473 OCCallbackData cbdata;
475 cbdata.context = static_cast<void*>(context),
476 cbdata.cb = listenDeviceCallback;
477 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
479 auto cLock = m_csdkLock.lock();
482 std::lock_guard<std::recursive_mutex> lock(*cLock);
483 result = OCDoResource(nullptr, OC_REST_DISCOVER,
484 deviceUri.str().c_str(),
485 nullptr, nullptr, connectivityType,
486 static_cast<OCQualityOfService>(QoS),
493 result = OC_STACK_ERROR;
498 void parseServerHeaderOptions(OCClientResponse* clientResponse,
499 HeaderOptions& serverHeaderOptions)
503 // Parse header options from server
505 std::string optionData;
507 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
509 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
510 optionData = reinterpret_cast<const char*>
511 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
512 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
513 serverHeaderOptions.push_back(headerOption);
518 // clientResponse is invalid
519 // TODO check proper logging
520 std::cout << " Invalid response " << std::endl;
525 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
526 OCClientResponse* clientResponse)
528 ClientCallbackContext::MQTopicContext* context =
529 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
530 HeaderOptions serverHeaderOptions;
532 if (!clientResponse || !context)
534 return OC_STACK_DELETE_TRANSACTION;
537 std::string createdUri;
538 bool isLocationOption = false;
539 OCStackResult result = clientResponse->result;
540 if (OC_STACK_OK == result ||
541 OC_STACK_RESOURCE_CREATED == result)
543 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
545 for (auto headerOption : serverHeaderOptions)
547 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
550 createdUri += headerOption.getOptionData();
551 if (!isLocationOption)
553 isLocationOption = true;
559 if (!isLocationOption)
561 createdUri = std::string(clientResponse->resourceUri);
564 auto clientWrapper = context->clientWrapper.lock();
568 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
570 return OC_STACK_DELETE_TRANSACTION;
575 if (OC_STACK_OK == result ||
576 OC_STACK_RESOURCE_CREATED == result)
578 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
580 for (auto resource : container.Resources())
582 std::thread exec(context->callback, result,
590 std::thread exec(context->callback, result,
596 catch (std::exception &e)
598 oclog() << "Exception in createMQTopicCallback, ignoring response: "
599 << e.what() << std::flush;
601 return OC_STACK_DELETE_TRANSACTION;
604 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
605 const OCDevAddr& devAddr,
606 const std::string& uri,
607 const OCRepresentation& rep,
608 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
609 MQTopicCallback& callback, QualityOfService QoS)
613 return OC_STACK_INVALID_PARAM;
615 OCStackResult result;
616 ClientCallbackContext::MQTopicContext* ctx =
617 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
618 OCCallbackData cbdata;
619 cbdata.context = static_cast<void*>(ctx),
620 cbdata.cb = createMQTopicCallback;
621 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
623 std::string url = assembleSetResourceUri(uri, queryParams);
625 auto cLock = m_csdkLock.lock();
629 std::lock_guard<std::recursive_mutex> lock(*cLock);
630 OCHeaderOption options[MAX_HEADER_OPTIONS];
632 result = OCDoResource(nullptr, OC_REST_PUT,
633 url.c_str(), &devAddr,
634 assembleSetResourcePayload(rep),
636 static_cast<OCQualityOfService>(QoS),
638 assembleHeaderOptions(options, headerOptions),
639 headerOptions.size());
644 result = OC_STACK_ERROR;
650 OCStackApplicationResult getResourceCallback(void* ctx,
651 OCDoHandle /*handle*/,
652 OCClientResponse* clientResponse)
654 ClientCallbackContext::GetContext* context =
655 static_cast<ClientCallbackContext::GetContext*>(ctx);
657 OCRepresentation rep;
658 HeaderOptions serverHeaderOptions;
659 OCStackResult result = clientResponse->result;
660 if (result == OC_STACK_OK)
662 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
665 rep = parseGetSetCallback(clientResponse);
667 catch(OC::OCException& e)
673 std::thread exec(context->callback, serverHeaderOptions, rep, result);
675 return OC_STACK_DELETE_TRANSACTION;
678 OCStackResult InProcClientWrapper::GetResourceRepresentation(
679 const OCDevAddr& devAddr,
680 const std::string& resourceUri,
681 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
682 OCConnectivityType connectivityType,
683 GetCallback& callback, QualityOfService QoS)
687 return OC_STACK_INVALID_PARAM;
689 OCStackResult result;
690 ClientCallbackContext::GetContext* ctx =
691 new ClientCallbackContext::GetContext(callback);
692 OCCallbackData cbdata;
693 cbdata.context = static_cast<void*>(ctx),
694 cbdata.cb = getResourceCallback;
695 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
698 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
700 auto cLock = m_csdkLock.lock();
704 std::lock_guard<std::recursive_mutex> lock(*cLock);
705 OCHeaderOption options[MAX_HEADER_OPTIONS];
707 result = OCDoResource(
708 nullptr, OC_REST_GET,
712 static_cast<OCQualityOfService>(QoS),
714 assembleHeaderOptions(options, headerOptions),
715 headerOptions.size());
720 result = OC_STACK_ERROR;
726 OCStackApplicationResult setResourceCallback(void* ctx,
727 OCDoHandle /*handle*/,
728 OCClientResponse* clientResponse)
730 ClientCallbackContext::SetContext* context =
731 static_cast<ClientCallbackContext::SetContext*>(ctx);
732 OCRepresentation attrs;
733 HeaderOptions serverHeaderOptions;
735 OCStackResult result = clientResponse->result;
736 if (OC_STACK_OK == result ||
737 OC_STACK_RESOURCE_CREATED == result ||
738 OC_STACK_RESOURCE_DELETED == result ||
739 OC_STACK_RESOURCE_CHANGED == result)
741 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
744 attrs = parseGetSetCallback(clientResponse);
746 catch(OC::OCException& e)
752 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
754 return OC_STACK_DELETE_TRANSACTION;
757 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
758 const QueryParamsMap& queryParams)
762 if (uri.back() == '/')
764 uri.resize(uri.size() - 1);
768 ostringstream paramsList;
769 if (queryParams.size() > 0)
774 for (auto& param : queryParams)
776 paramsList << param.first <<'='<<param.second<<';';
779 std::string queryString = paramsList.str();
781 if (queryString.empty())
786 if (queryString.back() == ';')
788 queryString.resize(queryString.size() - 1);
791 std::string ret = uri + queryString;
795 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
796 const QueryParamsList& queryParams)
800 if (uri.back() == '/')
802 uri.resize(uri.size() - 1);
806 ostringstream paramsList;
807 if (queryParams.size() > 0)
812 for (auto& param : queryParams)
814 for (auto& paramList : param.second)
816 paramsList << param.first << '=' << paramList << ';';
820 std::string queryString = paramsList.str();
822 if (queryString.empty())
827 if (queryString.back() == ';')
829 queryString.resize(queryString.size() - 1);
832 std::string ret = uri + queryString;
836 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
838 MessageContainer ocInfo;
839 ocInfo.addRepresentation(rep);
840 for(const OCRepresentation& r : rep.getChildren())
842 ocInfo.addRepresentation(r);
845 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
848 OCStackResult InProcClientWrapper::PostResourceRepresentation(
849 const OCDevAddr& devAddr,
850 const std::string& uri,
851 const OCRepresentation& rep,
852 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
853 OCConnectivityType connectivityType,
854 PostCallback& callback, QualityOfService QoS)
858 return OC_STACK_INVALID_PARAM;
860 OCStackResult result;
861 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
862 OCCallbackData cbdata;
863 cbdata.context = static_cast<void*>(ctx),
864 cbdata.cb = setResourceCallback;
865 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
868 std::string url = assembleSetResourceUri(uri, queryParams);
870 auto cLock = m_csdkLock.lock();
874 std::lock_guard<std::recursive_mutex> lock(*cLock);
875 OCHeaderOption options[MAX_HEADER_OPTIONS];
877 result = OCDoResource(nullptr, OC_REST_POST,
878 url.c_str(), &devAddr,
879 assembleSetResourcePayload(rep),
881 static_cast<OCQualityOfService>(QoS),
883 assembleHeaderOptions(options, headerOptions),
884 headerOptions.size());
889 result = OC_STACK_ERROR;
895 OCStackResult InProcClientWrapper::PutResourceRepresentation(
896 const OCDevAddr& devAddr,
897 const std::string& uri,
898 const OCRepresentation& rep,
899 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
900 PutCallback& callback, QualityOfService QoS)
904 return OC_STACK_INVALID_PARAM;
906 OCStackResult result;
907 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
908 OCCallbackData cbdata;
909 cbdata.context = static_cast<void*>(ctx),
910 cbdata.cb = setResourceCallback;
911 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
914 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
916 auto cLock = m_csdkLock.lock();
920 std::lock_guard<std::recursive_mutex> lock(*cLock);
922 OCHeaderOption options[MAX_HEADER_OPTIONS];
924 result = OCDoResource(&handle, OC_REST_PUT,
925 url.c_str(), &devAddr,
926 assembleSetResourcePayload(rep),
928 static_cast<OCQualityOfService>(QoS),
930 assembleHeaderOptions(options, headerOptions),
931 headerOptions.size());
936 result = OC_STACK_ERROR;
942 OCStackApplicationResult deleteResourceCallback(void* ctx,
943 OCDoHandle /*handle*/,
944 OCClientResponse* clientResponse)
946 ClientCallbackContext::DeleteContext* context =
947 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
948 HeaderOptions serverHeaderOptions;
950 if (clientResponse->result == OC_STACK_OK)
952 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
954 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
956 return OC_STACK_DELETE_TRANSACTION;
959 OCStackResult InProcClientWrapper::DeleteResource(
960 const OCDevAddr& devAddr,
961 const std::string& uri,
962 const HeaderOptions& headerOptions,
963 OCConnectivityType connectivityType,
964 DeleteCallback& callback,
965 QualityOfService /*QoS*/)
969 return OC_STACK_INVALID_PARAM;
971 OCStackResult result;
972 ClientCallbackContext::DeleteContext* ctx =
973 new ClientCallbackContext::DeleteContext(callback);
974 OCCallbackData cbdata;
975 cbdata.context = static_cast<void*>(ctx),
976 cbdata.cb = deleteResourceCallback;
977 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
980 auto cLock = m_csdkLock.lock();
984 OCHeaderOption options[MAX_HEADER_OPTIONS];
986 std::lock_guard<std::recursive_mutex> lock(*cLock);
988 result = OCDoResource(nullptr, OC_REST_DELETE,
989 uri.c_str(), &devAddr,
992 static_cast<OCQualityOfService>(m_cfg.QoS),
994 assembleHeaderOptions(options, headerOptions),
995 headerOptions.size());
1000 result = OC_STACK_ERROR;
1006 OCStackApplicationResult observeResourceCallback(void* ctx,
1007 OCDoHandle /*handle*/,
1008 OCClientResponse* clientResponse)
1010 ClientCallbackContext::ObserveContext* context =
1011 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1012 OCRepresentation attrs;
1013 HeaderOptions serverHeaderOptions;
1014 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1015 OCStackResult result = clientResponse->result;
1016 if (clientResponse->result == OC_STACK_OK)
1018 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1021 attrs = parseGetSetCallback(clientResponse);
1023 catch(OC::OCException& e)
1028 std::thread exec(context->callback, serverHeaderOptions, attrs,
1029 result, sequenceNumber);
1031 if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
1033 return OC_STACK_DELETE_TRANSACTION;
1036 return OC_STACK_KEEP_TRANSACTION;
1039 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1040 const OCDevAddr& devAddr,
1041 const std::string& uri,
1042 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1043 ObserveCallback& callback, QualityOfService QoS)
1047 return OC_STACK_INVALID_PARAM;
1049 OCStackResult result;
1051 ClientCallbackContext::ObserveContext* ctx =
1052 new ClientCallbackContext::ObserveContext(callback);
1053 OCCallbackData cbdata;
1054 cbdata.context = static_cast<void*>(ctx),
1055 cbdata.cb = observeResourceCallback;
1056 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1060 if (observeType == ObserveType::Observe)
1062 method = OC_REST_OBSERVE;
1064 else if (observeType == ObserveType::ObserveAll)
1066 method = OC_REST_OBSERVE_ALL;
1070 method = OC_REST_OBSERVE_ALL;
1073 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1075 auto cLock = m_csdkLock.lock();
1079 std::lock_guard<std::recursive_mutex> lock(*cLock);
1080 OCHeaderOption options[MAX_HEADER_OPTIONS];
1082 result = OCDoResource(handle, method,
1083 url.c_str(), &devAddr,
1086 static_cast<OCQualityOfService>(QoS),
1088 assembleHeaderOptions(options, headerOptions),
1089 headerOptions.size());
1094 return OC_STACK_ERROR;
1100 OCStackResult InProcClientWrapper::CancelObserveResource(
1102 const std::string& /*host*/,
1103 const std::string& /*uri*/,
1104 const HeaderOptions& headerOptions,
1105 QualityOfService QoS)
1107 OCStackResult result;
1108 auto cLock = m_csdkLock.lock();
1112 std::lock_guard<std::recursive_mutex> lock(*cLock);
1113 OCHeaderOption options[MAX_HEADER_OPTIONS];
1115 result = OCCancel(handle,
1116 static_cast<OCQualityOfService>(QoS),
1117 assembleHeaderOptions(options, headerOptions),
1118 headerOptions.size());
1122 result = OC_STACK_ERROR;
1128 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1129 OCDoHandle /*handle*/,
1130 OCClientResponse* clientResponse)
1132 ClientCallbackContext::SubscribePresenceContext* context =
1133 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1136 * This a hack while we rethink presence subscription.
1138 std::string url = clientResponse->devAddr.addr;
1140 std::thread exec(context->callback, clientResponse->result,
1141 clientResponse->sequenceNumber, url);
1145 return OC_STACK_KEEP_TRANSACTION;
1148 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1149 const std::string& host, const std::string& resourceType,
1150 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1152 if (!presenceHandler)
1154 return OC_STACK_INVALID_PARAM;
1157 ClientCallbackContext::SubscribePresenceContext* ctx =
1158 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1159 OCCallbackData cbdata;
1160 cbdata.context = static_cast<void*>(ctx),
1161 cbdata.cb = subscribePresenceCallback;
1162 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1165 auto cLock = m_csdkLock.lock();
1167 std::ostringstream os;
1168 os << host << OC_RSRVD_PRESENCE_URI;
1170 if (!resourceType.empty())
1172 os << "?rt=" << resourceType;
1178 return OC_STACK_ERROR;
1181 return OCDoResource(handle, OC_REST_PRESENCE,
1182 os.str().c_str(), nullptr,
1183 nullptr, connectivityType,
1184 OC_LOW_QOS, &cbdata, NULL, 0);
1187 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1189 OCStackResult result;
1190 auto cLock = m_csdkLock.lock();
1194 std::lock_guard<std::recursive_mutex> lock(*cLock);
1195 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1199 result = OC_STACK_ERROR;
1206 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1207 const std::string& host,
1208 const std::vector<std::string>& di,
1209 OCConnectivityType connectivityType,
1210 ObserveCallback& callback)
1214 return OC_STACK_INVALID_PARAM;
1216 OCStackResult result;
1218 ClientCallbackContext::ObserveContext* ctx =
1219 new ClientCallbackContext::ObserveContext(callback);
1220 OCCallbackData cbdata;
1221 cbdata.context = static_cast<void*>(ctx),
1222 cbdata.cb = observeResourceCallback;
1223 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1225 auto cLock = m_csdkLock.lock();
1229 std::lock_guard<std::recursive_mutex> lock(*cLock);
1231 std::ostringstream os;
1232 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1233 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1234 std::string url = assembleSetResourceUri(os.str(), queryParams);
1236 result = OCDoResource(handle, OC_REST_OBSERVE,
1237 url.c_str(), nullptr,
1238 nullptr, connectivityType,
1239 OC_LOW_QOS, &cbdata,
1245 result = OC_STACK_ERROR;
1252 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1258 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1259 const HeaderOptions& headerOptions)
1263 if ( headerOptions.size() == 0)
1268 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1270 options[i] = OCHeaderOption();
1271 options[i].protocolID = OC_COAP_ID;
1272 options[i].optionID = it->getOptionID();
1273 options[i].optionLength = it->getOptionData().length() + 1;
1274 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1281 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1288 OCDPDev_t* result = new OCDPDev_t(*dev);
1289 result->prm = new OCPrm_t[dev->prmLen];
1290 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1291 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1294 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1298 dpList.push_back(cloneDevice(list));
1303 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1304 GetDirectPairedCallback& callback)
1306 if (!callback || 0 == waittime)
1308 return OC_STACK_INVALID_PARAM;
1311 OCStackResult result = OC_STACK_ERROR;
1312 const OCDPDev_t *list = nullptr;
1313 PairedDevices dpDeviceList;
1315 auto cLock = m_csdkLock.lock();
1319 std::lock_guard<std::recursive_mutex> lock(*cLock);
1321 list = OCDiscoverDirectPairingDevices(waittime);
1324 result = OC_STACK_NO_RESOURCE;
1325 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1329 convert(list, dpDeviceList);
1330 std::thread exec(callback, dpDeviceList);
1332 result = OC_STACK_OK;
1337 result = OC_STACK_ERROR;
1343 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1347 return OC_STACK_INVALID_PARAM;
1350 OCStackResult result = OC_STACK_ERROR;
1351 const OCDPDev_t *list = nullptr;
1352 PairedDevices dpDeviceList;
1354 auto cLock = m_csdkLock.lock();
1358 std::lock_guard<std::recursive_mutex> lock(*cLock);
1360 list = OCGetDirectPairedDevices();
1363 result = OC_STACK_NO_RESOURCE;
1364 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1368 convert(list, dpDeviceList);
1369 std::thread exec(callback, dpDeviceList);
1371 result = OC_STACK_OK;
1376 result = OC_STACK_ERROR;
1382 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1383 OCStackResult result)
1386 ClientCallbackContext::DirectPairingContext* context =
1387 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1389 std::thread exec(context->callback, cloneDevice(peer), result);
1393 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1394 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1396 if (!peer || !callback)
1398 oclog() << "Invalid parameters" << std::flush;
1399 return OC_STACK_INVALID_PARAM;
1402 OCStackResult result = OC_STACK_ERROR;
1403 ClientCallbackContext::DirectPairingContext* context =
1404 new ClientCallbackContext::DirectPairingContext(callback);
1406 auto cLock = m_csdkLock.lock();
1409 std::lock_guard<std::recursive_mutex> lock(*cLock);
1410 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1411 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1416 result = OC_STACK_ERROR;