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_DELETE_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 if (clientResponse->result != OC_STACK_OK)
344 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
345 << clientResponse->result
348 std::thread exec(context->callback, clientResponse->result,
349 clientResponse->resourceUri, nullptr);
352 return OC_STACK_DELETE_TRANSACTION;
355 auto clientWrapper = context->clientWrapper.lock();
358 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
360 return OC_STACK_DELETE_TRANSACTION;
365 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
366 (OCRepPayload *) clientResponse->payload);
368 // loop to ensure valid construction of all resources
369 for (auto resource : container.Resources())
371 std::thread exec(context->callback, clientResponse->result,
372 clientResponse->resourceUri, resource);
376 catch (std::exception &e)
378 oclog() << "Exception in listCallback, ignoring response: "
379 << e.what() << std::flush;
382 return OC_STACK_DELETE_TRANSACTION;
385 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
386 const std::string& resourceUri,
387 const QueryParamsMap& queryParams,
388 const HeaderOptions& headerOptions,
389 MQTopicCallback& callback,
390 QualityOfService QoS)
392 oclog() << "ListenForMQTopic()" << std::flush;
396 return OC_STACK_INVALID_PARAM;
399 ClientCallbackContext::MQTopicContext* context =
400 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
401 OCCallbackData cbdata;
402 cbdata.context = static_cast<void*>(context),
403 cbdata.cb = listenMQCallback;
404 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
406 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
408 OCStackResult result = OC_STACK_ERROR;
409 auto cLock = m_csdkLock.lock();
412 std::lock_guard<std::recursive_mutex> lock(*cLock);
413 OCHeaderOption options[MAX_HEADER_OPTIONS];
414 result = OCDoResource(
415 nullptr, OC_REST_GET,
419 static_cast<OCQualityOfService>(QoS),
421 assembleHeaderOptions(options, headerOptions),
422 headerOptions.size());
433 OCStackApplicationResult listenDeviceCallback(void* ctx,
434 OCDoHandle /*handle*/,
435 OCClientResponse* clientResponse)
437 ClientCallbackContext::DeviceListenContext* context =
438 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
442 OCRepresentation rep = parseGetSetCallback(clientResponse);
443 std::thread exec(context->callback, rep);
446 catch(OC::OCException& e)
448 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
449 <<e.what() <<std::flush;
452 return OC_STACK_KEEP_TRANSACTION;
455 OCStackResult InProcClientWrapper::ListenForDevice(
456 const std::string& serviceUrl,
457 const std::string& deviceURI,
458 OCConnectivityType connectivityType,
459 FindDeviceCallback& callback,
460 QualityOfService QoS)
464 return OC_STACK_INVALID_PARAM;
466 OCStackResult result;
467 ostringstream deviceUri;
468 deviceUri << serviceUrl << deviceURI;
470 ClientCallbackContext::DeviceListenContext* context =
471 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
472 OCCallbackData cbdata;
474 cbdata.context = static_cast<void*>(context),
475 cbdata.cb = listenDeviceCallback;
476 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
478 auto cLock = m_csdkLock.lock();
481 std::lock_guard<std::recursive_mutex> lock(*cLock);
482 result = OCDoResource(nullptr, OC_REST_DISCOVER,
483 deviceUri.str().c_str(),
484 nullptr, nullptr, connectivityType,
485 static_cast<OCQualityOfService>(QoS),
492 result = OC_STACK_ERROR;
497 void parseServerHeaderOptions(OCClientResponse* clientResponse,
498 HeaderOptions& serverHeaderOptions)
502 // Parse header options from server
504 std::string optionData;
506 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
508 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
509 optionData = reinterpret_cast<const char*>
510 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
511 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
512 serverHeaderOptions.push_back(headerOption);
517 // clientResponse is invalid
518 // TODO check proper logging
519 std::cout << " Invalid response " << std::endl;
524 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
525 OCClientResponse* clientResponse)
527 ClientCallbackContext::MQTopicContext* context =
528 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
529 HeaderOptions serverHeaderOptions;
531 if (!clientResponse || !context)
533 return OC_STACK_DELETE_TRANSACTION;
536 std::string createdUri;
537 bool isLocationOption = false;
538 OCStackResult result = clientResponse->result;
539 if (OC_STACK_OK == result ||
540 OC_STACK_RESOURCE_CREATED == result)
542 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
544 for (auto headerOption : serverHeaderOptions)
546 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
549 createdUri += headerOption.getOptionData();
550 if (!isLocationOption)
552 isLocationOption = true;
558 if (!isLocationOption)
560 createdUri = clientResponse->resourceUri;
563 auto clientWrapper = context->clientWrapper.lock();
567 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
569 return OC_STACK_DELETE_TRANSACTION;
574 if (OC_STACK_OK == result ||
575 OC_STACK_RESOURCE_CREATED == result)
577 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
579 for (auto resource : container.Resources())
581 std::thread exec(context->callback, result, createdUri, resource);
587 std::thread exec(context->callback, result, createdUri, nullptr);
591 catch (std::exception &e)
593 oclog() << "Exception in createMQTopicCallback, ignoring response: "
594 << e.what() << std::flush;
596 return OC_STACK_DELETE_TRANSACTION;
599 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
600 const OCDevAddr& devAddr,
601 const std::string& uri,
602 const OCRepresentation& rep,
603 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
604 MQTopicCallback& callback, QualityOfService QoS)
608 return OC_STACK_INVALID_PARAM;
610 OCStackResult result;
611 ClientCallbackContext::MQTopicContext* ctx =
612 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
613 OCCallbackData cbdata;
614 cbdata.context = static_cast<void*>(ctx),
615 cbdata.cb = createMQTopicCallback;
616 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
618 std::string url = assembleSetResourceUri(uri, queryParams);
620 auto cLock = m_csdkLock.lock();
624 std::lock_guard<std::recursive_mutex> lock(*cLock);
625 OCHeaderOption options[MAX_HEADER_OPTIONS];
627 result = OCDoResource(nullptr, OC_REST_PUT,
628 url.c_str(), &devAddr,
629 assembleSetResourcePayload(rep),
631 static_cast<OCQualityOfService>(QoS),
633 assembleHeaderOptions(options, headerOptions),
634 headerOptions.size());
639 result = OC_STACK_ERROR;
645 OCStackApplicationResult getResourceCallback(void* ctx,
646 OCDoHandle /*handle*/,
647 OCClientResponse* clientResponse)
649 ClientCallbackContext::GetContext* context =
650 static_cast<ClientCallbackContext::GetContext*>(ctx);
652 OCRepresentation rep;
653 HeaderOptions serverHeaderOptions;
654 OCStackResult result = clientResponse->result;
655 if (result == OC_STACK_OK)
657 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
660 rep = parseGetSetCallback(clientResponse);
662 catch(OC::OCException& e)
668 std::thread exec(context->callback, serverHeaderOptions, rep, result);
670 return OC_STACK_DELETE_TRANSACTION;
673 OCStackResult InProcClientWrapper::GetResourceRepresentation(
674 const OCDevAddr& devAddr,
675 const std::string& resourceUri,
676 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
677 OCConnectivityType connectivityType,
678 GetCallback& callback, QualityOfService QoS)
682 return OC_STACK_INVALID_PARAM;
684 OCStackResult result;
685 ClientCallbackContext::GetContext* ctx =
686 new ClientCallbackContext::GetContext(callback);
687 OCCallbackData cbdata;
688 cbdata.context = static_cast<void*>(ctx),
689 cbdata.cb = getResourceCallback;
690 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
693 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
695 auto cLock = m_csdkLock.lock();
699 std::lock_guard<std::recursive_mutex> lock(*cLock);
700 OCHeaderOption options[MAX_HEADER_OPTIONS];
702 result = OCDoResource(
703 nullptr, OC_REST_GET,
707 static_cast<OCQualityOfService>(QoS),
709 assembleHeaderOptions(options, headerOptions),
710 headerOptions.size());
715 result = OC_STACK_ERROR;
721 OCStackApplicationResult setResourceCallback(void* ctx,
722 OCDoHandle /*handle*/,
723 OCClientResponse* clientResponse)
725 ClientCallbackContext::SetContext* context =
726 static_cast<ClientCallbackContext::SetContext*>(ctx);
727 OCRepresentation attrs;
728 HeaderOptions serverHeaderOptions;
730 OCStackResult result = clientResponse->result;
731 if (OC_STACK_OK == result ||
732 OC_STACK_RESOURCE_CREATED == result ||
733 OC_STACK_RESOURCE_DELETED == result ||
734 OC_STACK_RESOURCE_CHANGED == result)
736 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
739 attrs = parseGetSetCallback(clientResponse);
741 catch(OC::OCException& e)
747 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
749 return OC_STACK_DELETE_TRANSACTION;
752 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
753 const QueryParamsMap& queryParams)
757 if (uri.back() == '/')
759 uri.resize(uri.size() - 1);
763 ostringstream paramsList;
764 if (queryParams.size() > 0)
769 for (auto& param : queryParams)
771 paramsList << param.first <<'='<<param.second<<';';
774 std::string queryString = paramsList.str();
776 if (queryString.empty())
781 if (queryString.back() == ';')
783 queryString.resize(queryString.size() - 1);
786 std::string ret = uri + queryString;
790 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
791 const QueryParamsList& queryParams)
795 if (uri.back() == '/')
797 uri.resize(uri.size() - 1);
801 ostringstream paramsList;
802 if (queryParams.size() > 0)
807 for (auto& param : queryParams)
809 for (auto& paramList : param.second)
811 paramsList << param.first << '=' << paramList << ';';
815 std::string queryString = paramsList.str();
817 if (queryString.empty())
822 if (queryString.back() == ';')
824 queryString.resize(queryString.size() - 1);
827 std::string ret = uri + queryString;
831 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
833 MessageContainer ocInfo;
834 ocInfo.addRepresentation(rep);
835 for(const OCRepresentation& r : rep.getChildren())
837 ocInfo.addRepresentation(r);
840 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
843 OCStackResult InProcClientWrapper::PostResourceRepresentation(
844 const OCDevAddr& devAddr,
845 const std::string& uri,
846 const OCRepresentation& rep,
847 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
848 OCConnectivityType connectivityType,
849 PostCallback& callback, QualityOfService QoS)
853 return OC_STACK_INVALID_PARAM;
855 OCStackResult result;
856 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
857 OCCallbackData cbdata;
858 cbdata.context = static_cast<void*>(ctx),
859 cbdata.cb = setResourceCallback;
860 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
863 std::string url = assembleSetResourceUri(uri, queryParams);
865 auto cLock = m_csdkLock.lock();
869 std::lock_guard<std::recursive_mutex> lock(*cLock);
870 OCHeaderOption options[MAX_HEADER_OPTIONS];
872 result = OCDoResource(nullptr, OC_REST_POST,
873 url.c_str(), &devAddr,
874 assembleSetResourcePayload(rep),
876 static_cast<OCQualityOfService>(QoS),
878 assembleHeaderOptions(options, headerOptions),
879 headerOptions.size());
884 result = OC_STACK_ERROR;
890 OCStackResult InProcClientWrapper::PutResourceRepresentation(
891 const OCDevAddr& devAddr,
892 const std::string& uri,
893 const OCRepresentation& rep,
894 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
895 PutCallback& callback, QualityOfService QoS)
899 return OC_STACK_INVALID_PARAM;
901 OCStackResult result;
902 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
903 OCCallbackData cbdata;
904 cbdata.context = static_cast<void*>(ctx),
905 cbdata.cb = setResourceCallback;
906 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
909 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
911 auto cLock = m_csdkLock.lock();
915 std::lock_guard<std::recursive_mutex> lock(*cLock);
917 OCHeaderOption options[MAX_HEADER_OPTIONS];
919 result = OCDoResource(&handle, OC_REST_PUT,
920 url.c_str(), &devAddr,
921 assembleSetResourcePayload(rep),
923 static_cast<OCQualityOfService>(QoS),
925 assembleHeaderOptions(options, headerOptions),
926 headerOptions.size());
931 result = OC_STACK_ERROR;
937 OCStackApplicationResult deleteResourceCallback(void* ctx,
938 OCDoHandle /*handle*/,
939 OCClientResponse* clientResponse)
941 ClientCallbackContext::DeleteContext* context =
942 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
943 HeaderOptions serverHeaderOptions;
945 if (clientResponse->result == OC_STACK_OK)
947 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
949 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
951 return OC_STACK_DELETE_TRANSACTION;
954 OCStackResult InProcClientWrapper::DeleteResource(
955 const OCDevAddr& devAddr,
956 const std::string& uri,
957 const HeaderOptions& headerOptions,
958 OCConnectivityType connectivityType,
959 DeleteCallback& callback,
960 QualityOfService /*QoS*/)
964 return OC_STACK_INVALID_PARAM;
966 OCStackResult result;
967 ClientCallbackContext::DeleteContext* ctx =
968 new ClientCallbackContext::DeleteContext(callback);
969 OCCallbackData cbdata;
970 cbdata.context = static_cast<void*>(ctx),
971 cbdata.cb = deleteResourceCallback;
972 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
975 auto cLock = m_csdkLock.lock();
979 OCHeaderOption options[MAX_HEADER_OPTIONS];
981 std::lock_guard<std::recursive_mutex> lock(*cLock);
983 result = OCDoResource(nullptr, OC_REST_DELETE,
984 uri.c_str(), &devAddr,
987 static_cast<OCQualityOfService>(m_cfg.QoS),
989 assembleHeaderOptions(options, headerOptions),
990 headerOptions.size());
995 result = OC_STACK_ERROR;
1001 OCStackApplicationResult observeResourceCallback(void* ctx,
1002 OCDoHandle /*handle*/,
1003 OCClientResponse* clientResponse)
1005 ClientCallbackContext::ObserveContext* context =
1006 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1007 OCRepresentation attrs;
1008 HeaderOptions serverHeaderOptions;
1009 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1010 OCStackResult result = clientResponse->result;
1011 if (clientResponse->result == OC_STACK_OK)
1013 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1016 attrs = parseGetSetCallback(clientResponse);
1018 catch(OC::OCException& e)
1023 std::thread exec(context->callback, serverHeaderOptions, attrs,
1024 result, sequenceNumber);
1027 return OC_STACK_KEEP_TRANSACTION;
1030 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1031 const OCDevAddr& devAddr,
1032 const std::string& uri,
1033 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1034 ObserveCallback& callback, QualityOfService QoS)
1038 return OC_STACK_INVALID_PARAM;
1040 OCStackResult result;
1042 ClientCallbackContext::ObserveContext* ctx =
1043 new ClientCallbackContext::ObserveContext(callback);
1044 OCCallbackData cbdata;
1045 cbdata.context = static_cast<void*>(ctx),
1046 cbdata.cb = observeResourceCallback;
1047 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1051 if (observeType == ObserveType::Observe)
1053 method = OC_REST_OBSERVE;
1055 else if (observeType == ObserveType::ObserveAll)
1057 method = OC_REST_OBSERVE_ALL;
1061 method = OC_REST_OBSERVE_ALL;
1064 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1066 auto cLock = m_csdkLock.lock();
1070 std::lock_guard<std::recursive_mutex> lock(*cLock);
1071 OCHeaderOption options[MAX_HEADER_OPTIONS];
1073 result = OCDoResource(handle, method,
1074 url.c_str(), &devAddr,
1077 static_cast<OCQualityOfService>(QoS),
1079 assembleHeaderOptions(options, headerOptions),
1080 headerOptions.size());
1085 return OC_STACK_ERROR;
1091 OCStackResult InProcClientWrapper::CancelObserveResource(
1093 const std::string& /*host*/,
1094 const std::string& /*uri*/,
1095 const HeaderOptions& headerOptions,
1096 QualityOfService QoS)
1098 OCStackResult result;
1099 auto cLock = m_csdkLock.lock();
1103 std::lock_guard<std::recursive_mutex> lock(*cLock);
1104 OCHeaderOption options[MAX_HEADER_OPTIONS];
1106 result = OCCancel(handle,
1107 static_cast<OCQualityOfService>(QoS),
1108 assembleHeaderOptions(options, headerOptions),
1109 headerOptions.size());
1113 result = OC_STACK_ERROR;
1119 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1120 OCDoHandle /*handle*/,
1121 OCClientResponse* clientResponse)
1123 ClientCallbackContext::SubscribePresenceContext* context =
1124 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1127 * This a hack while we rethink presence subscription.
1129 std::string url = clientResponse->devAddr.addr;
1131 std::thread exec(context->callback, clientResponse->result,
1132 clientResponse->sequenceNumber, url);
1136 return OC_STACK_KEEP_TRANSACTION;
1139 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1140 const std::string& host, const std::string& resourceType,
1141 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1143 if (!presenceHandler)
1145 return OC_STACK_INVALID_PARAM;
1148 ClientCallbackContext::SubscribePresenceContext* ctx =
1149 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1150 OCCallbackData cbdata;
1151 cbdata.context = static_cast<void*>(ctx),
1152 cbdata.cb = subscribePresenceCallback;
1153 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1156 auto cLock = m_csdkLock.lock();
1158 std::ostringstream os;
1159 os << host << OC_RSRVD_PRESENCE_URI;
1161 if (!resourceType.empty())
1163 os << "?rt=" << resourceType;
1169 return OC_STACK_ERROR;
1172 return OCDoResource(handle, OC_REST_PRESENCE,
1173 os.str().c_str(), nullptr,
1174 nullptr, connectivityType,
1175 OC_LOW_QOS, &cbdata, NULL, 0);
1178 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1180 OCStackResult result;
1181 auto cLock = m_csdkLock.lock();
1185 std::lock_guard<std::recursive_mutex> lock(*cLock);
1186 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1190 result = OC_STACK_ERROR;
1197 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1198 const std::string& host,
1199 const std::vector<std::string>& di,
1200 OCConnectivityType connectivityType,
1201 ObserveCallback& callback)
1205 return OC_STACK_INVALID_PARAM;
1207 OCStackResult result;
1209 ClientCallbackContext::ObserveContext* ctx =
1210 new ClientCallbackContext::ObserveContext(callback);
1211 OCCallbackData cbdata;
1212 cbdata.context = static_cast<void*>(ctx),
1213 cbdata.cb = observeResourceCallback;
1214 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1216 auto cLock = m_csdkLock.lock();
1220 std::lock_guard<std::recursive_mutex> lock(*cLock);
1222 std::ostringstream os;
1223 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1224 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1225 std::string url = assembleSetResourceUri(os.str(), queryParams);
1227 result = OCDoResource(handle, OC_REST_OBSERVE,
1228 url.c_str(), nullptr,
1229 nullptr, connectivityType,
1230 OC_LOW_QOS, &cbdata,
1236 result = OC_STACK_ERROR;
1243 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1249 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1250 const HeaderOptions& headerOptions)
1254 if ( headerOptions.size() == 0)
1259 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1261 options[i] = OCHeaderOption();
1262 options[i].protocolID = OC_COAP_ID;
1263 options[i].optionID = it->getOptionID();
1264 options[i].optionLength = it->getOptionData().length() + 1;
1265 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1272 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1279 OCDPDev_t* result = new OCDPDev_t(*dev);
1280 result->prm = new OCPrm_t[dev->prmLen];
1281 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1282 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1285 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1289 dpList.push_back(cloneDevice(list));
1294 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1295 GetDirectPairedCallback& callback)
1297 if (!callback || 0 == waittime)
1299 return OC_STACK_INVALID_PARAM;
1302 OCStackResult result = OC_STACK_ERROR;
1303 const OCDPDev_t *list = nullptr;
1304 PairedDevices dpDeviceList;
1306 auto cLock = m_csdkLock.lock();
1310 std::lock_guard<std::recursive_mutex> lock(*cLock);
1312 list = OCDiscoverDirectPairingDevices(waittime);
1315 result = OC_STACK_NO_RESOURCE;
1316 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1320 convert(list, dpDeviceList);
1321 std::thread exec(callback, dpDeviceList);
1323 result = OC_STACK_OK;
1328 result = OC_STACK_ERROR;
1334 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1338 return OC_STACK_INVALID_PARAM;
1341 OCStackResult result = OC_STACK_ERROR;
1342 const OCDPDev_t *list = nullptr;
1343 PairedDevices dpDeviceList;
1345 auto cLock = m_csdkLock.lock();
1349 std::lock_guard<std::recursive_mutex> lock(*cLock);
1351 list = OCGetDirectPairedDevices();
1354 result = OC_STACK_NO_RESOURCE;
1355 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1359 convert(list, dpDeviceList);
1360 std::thread exec(callback, dpDeviceList);
1362 result = OC_STACK_OK;
1367 result = OC_STACK_ERROR;
1373 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1374 OCStackResult result)
1377 ClientCallbackContext::DirectPairingContext* context =
1378 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1380 std::thread exec(context->callback, cloneDevice(peer), result);
1384 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1385 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1387 if (!peer || !callback)
1389 oclog() << "Invalid parameters" << std::flush;
1390 return OC_STACK_INVALID_PARAM;
1393 OCStackResult result = OC_STACK_ERROR;
1394 ClientCallbackContext::DirectPairingContext* context =
1395 new ClientCallbackContext::DirectPairingContext(callback);
1397 auto cLock = m_csdkLock.lock();
1400 std::lock_guard<std::recursive_mutex> lock(*cLock);
1401 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1402 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1407 result = OC_STACK_ERROR;