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;
169 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
170 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
171 // loop to ensure valid construction of all resources
173 for(auto resource : container.Resources())
175 std::thread exec(context->callback, resource);
179 catch (std::exception &e){
180 oclog() << "Exception in listCallback, ignoring response: "
181 << e.what() << std::flush;
185 return OC_STACK_KEEP_TRANSACTION;
188 OCStackApplicationResult listenErrorCallback(void* ctx, OCDoHandle /*handle*/,
189 OCClientResponse* clientResponse)
191 if (!ctx || !clientResponse)
193 return OC_STACK_KEEP_TRANSACTION;
196 ClientCallbackContext::ListenErrorContext* context =
197 static_cast<ClientCallbackContext::ListenErrorContext*>(ctx);
200 return OC_STACK_KEEP_TRANSACTION;
203 OCStackResult result = clientResponse->result;
204 if (result == OC_STACK_OK)
206 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
208 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
210 return OC_STACK_KEEP_TRANSACTION;
213 auto clientWrapper = context->clientWrapper.lock();
217 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
219 return OC_STACK_KEEP_TRANSACTION;
222 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
223 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
224 // loop to ensure valid construction of all resources
225 for (auto resource : container.Resources())
227 std::thread exec(context->callback, resource);
230 return OC_STACK_KEEP_TRANSACTION;
233 std::string resourceURI = clientResponse->resourceUri;
234 std::thread exec(context->errorCallback, resourceURI, result);
236 return OC_STACK_DELETE_TRANSACTION;
239 OCStackResult InProcClientWrapper::ListenForResource(
240 const std::string& serviceUrl,
241 const std::string& resourceType,
242 OCConnectivityType connectivityType,
243 FindCallback& callback, QualityOfService QoS)
247 return OC_STACK_INVALID_PARAM;
250 OCStackResult result;
251 ostringstream resourceUri;
252 resourceUri << serviceUrl << resourceType;
254 ClientCallbackContext::ListenContext* context =
255 new ClientCallbackContext::ListenContext(callback, shared_from_this());
256 OCCallbackData cbdata;
257 cbdata.context = static_cast<void*>(context),
258 cbdata.cb = listenCallback;
259 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
261 auto cLock = m_csdkLock.lock();
264 std::lock_guard<std::recursive_mutex> lock(*cLock);
265 result = OCDoResource(nullptr, OC_REST_DISCOVER,
266 resourceUri.str().c_str(),
267 nullptr, nullptr, connectivityType,
268 static_cast<OCQualityOfService>(QoS),
275 result = OC_STACK_ERROR;
280 OCStackResult InProcClientWrapper::ListenErrorForResource(
281 const std::string& serviceUrl,
282 const std::string& resourceType,
283 OCConnectivityType connectivityType,
284 FindCallback& callback, FindErrorCallback& errorCallback,
285 QualityOfService QoS)
289 return OC_STACK_INVALID_PARAM;
292 ostringstream resourceUri;
293 resourceUri << serviceUrl << resourceType;
295 ClientCallbackContext::ListenErrorContext* context =
296 new ClientCallbackContext::ListenErrorContext(callback, errorCallback,
300 return OC_STACK_ERROR;
303 OCCallbackData cbdata(
304 static_cast<void*>(context),
306 [](void* c){delete static_cast<ClientCallbackContext::ListenErrorContext*>(c);}
309 OCStackResult result;
310 auto cLock = m_csdkLock.lock();
313 std::lock_guard<std::recursive_mutex> lock(*cLock);
314 result = OCDoResource(nullptr, OC_REST_DISCOVER,
315 resourceUri.str().c_str(),
316 nullptr, nullptr, connectivityType,
317 static_cast<OCQualityOfService>(QoS),
324 result = OC_STACK_ERROR;
329 OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
330 OCClientResponse* clientResponse)
332 ClientCallbackContext::ListenContext* context =
333 static_cast<ClientCallbackContext::ListenContext*>(ctx);
337 return OC_STACK_KEEP_TRANSACTION;
340 if (clientResponse->result != OC_STACK_OK)
342 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
343 << clientResponse->result
346 return OC_STACK_KEEP_TRANSACTION;
349 auto clientWrapper = context->clientWrapper.lock();
352 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
354 return OC_STACK_KEEP_TRANSACTION;
358 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
359 (OCRepPayload *) clientResponse->payload);
361 // loop to ensure valid construction of all resources
362 for (auto resource : container.Resources())
364 std::thread exec(context->callback, resource);
368 catch (std::exception &e){
369 oclog() << "Exception in listCallback, ignoring response: "
370 << e.what() << std::flush;
374 return OC_STACK_KEEP_TRANSACTION;
377 OCStackResult InProcClientWrapper::ListenForMQTopic(
378 const OCDevAddr& devAddr,
379 const std::string& resourceUri,
380 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
381 FindCallback& callback, QualityOfService QoS)
383 oclog() << "ListenForMQTopic()" << std::flush;
387 return OC_STACK_INVALID_PARAM;
390 ClientCallbackContext::ListenContext* context =
391 new ClientCallbackContext::ListenContext(callback, shared_from_this());
392 OCCallbackData cbdata;
393 cbdata.context = static_cast<void*>(context),
394 cbdata.cb = listenMQCallback;
395 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
397 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
399 OCStackResult result = OC_STACK_ERROR;
400 auto cLock = m_csdkLock.lock();
403 std::lock_guard<std::recursive_mutex> lock(*cLock);
404 OCHeaderOption options[MAX_HEADER_OPTIONS];
405 result = OCDoResource(
406 nullptr, OC_REST_GET,
410 static_cast<OCQualityOfService>(QoS),
412 assembleHeaderOptions(options, headerOptions),
413 headerOptions.size());
424 OCStackApplicationResult listenDeviceCallback(void* ctx,
425 OCDoHandle /*handle*/,
426 OCClientResponse* clientResponse)
428 ClientCallbackContext::DeviceListenContext* context =
429 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
433 OCRepresentation rep = parseGetSetCallback(clientResponse);
434 std::thread exec(context->callback, rep);
437 catch(OC::OCException& e)
439 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
440 <<e.what() <<std::flush;
443 return OC_STACK_KEEP_TRANSACTION;
446 OCStackResult InProcClientWrapper::ListenForDevice(
447 const std::string& serviceUrl,
448 const std::string& deviceURI,
449 OCConnectivityType connectivityType,
450 FindDeviceCallback& callback,
451 QualityOfService QoS)
455 return OC_STACK_INVALID_PARAM;
457 OCStackResult result;
458 ostringstream deviceUri;
459 deviceUri << serviceUrl << deviceURI;
461 ClientCallbackContext::DeviceListenContext* context =
462 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
463 OCCallbackData cbdata;
465 cbdata.context = static_cast<void*>(context),
466 cbdata.cb = listenDeviceCallback;
467 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
469 auto cLock = m_csdkLock.lock();
472 std::lock_guard<std::recursive_mutex> lock(*cLock);
473 result = OCDoResource(nullptr, OC_REST_DISCOVER,
474 deviceUri.str().c_str(),
475 nullptr, nullptr, connectivityType,
476 static_cast<OCQualityOfService>(QoS),
483 result = OC_STACK_ERROR;
488 void parseServerHeaderOptions(OCClientResponse* clientResponse,
489 HeaderOptions& serverHeaderOptions)
493 // Parse header options from server
495 std::string optionData;
497 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
499 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
500 optionData = reinterpret_cast<const char*>
501 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
502 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
503 serverHeaderOptions.push_back(headerOption);
508 // clientResponse is invalid
509 // TODO check proper logging
510 std::cout << " Invalid response " << std::endl;
515 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
516 OCClientResponse* clientResponse)
518 ClientCallbackContext::CreateMQTopicContext* context =
519 static_cast<ClientCallbackContext::CreateMQTopicContext*>(ctx);
520 OCRepresentation rep;
521 HeaderOptions serverHeaderOptions;
525 return OC_STACK_DELETE_TRANSACTION;
528 std::string createdUri;
529 OCStackResult result = clientResponse->result;
530 if (OC_STACK_OK == result ||
531 OC_STACK_RESOURCE_CREATED == result)
533 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
536 rep = parseGetSetCallback(clientResponse);
538 catch(OC::OCException& e)
543 bool isLocationOption = false;
544 for (auto headerOption : serverHeaderOptions)
546 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
549 createdUri += headerOption.getOptionData();
550 if (!isLocationOption)
552 isLocationOption = true;
557 if (!isLocationOption)
559 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;
573 if (OC_STACK_OK == result ||
574 OC_STACK_RESOURCE_CREATED == result)
576 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
578 for (auto resource : container.Resources())
580 std::thread exec(context->callback, serverHeaderOptions, rep, result, resource);
586 std::thread exec(context->callback, serverHeaderOptions, rep, result, nullptr);
590 catch (std::exception &e){
591 oclog() << "Exception in createMQTopicCallback, ignoring response: "
592 << e.what() << std::flush;
594 return OC_STACK_DELETE_TRANSACTION;
597 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
598 const OCDevAddr& devAddr,
599 const std::string& uri,
600 const OCRepresentation& rep,
601 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
602 MQCreateTopicCallback& callback, QualityOfService QoS)
606 return OC_STACK_INVALID_PARAM;
608 OCStackResult result;
609 ClientCallbackContext::CreateMQTopicContext* ctx =
610 new ClientCallbackContext::CreateMQTopicContext(callback, shared_from_this());
611 OCCallbackData cbdata;
612 cbdata.context = static_cast<void*>(ctx),
613 cbdata.cb = createMQTopicCallback;
614 cbdata.cd = [](void* c){delete (ClientCallbackContext::CreateMQTopicContext*)c;};
616 std::string url = assembleSetResourceUri(uri, queryParams);
618 auto cLock = m_csdkLock.lock();
622 std::lock_guard<std::recursive_mutex> lock(*cLock);
623 OCHeaderOption options[MAX_HEADER_OPTIONS];
625 result = OCDoResource(nullptr, OC_REST_PUT,
626 url.c_str(), &devAddr,
627 assembleSetResourcePayload(rep),
629 static_cast<OCQualityOfService>(QoS),
631 assembleHeaderOptions(options, headerOptions),
632 headerOptions.size());
637 result = OC_STACK_ERROR;
643 OCStackApplicationResult getResourceCallback(void* ctx,
644 OCDoHandle /*handle*/,
645 OCClientResponse* clientResponse)
647 ClientCallbackContext::GetContext* context =
648 static_cast<ClientCallbackContext::GetContext*>(ctx);
650 OCRepresentation rep;
651 HeaderOptions serverHeaderOptions;
652 OCStackResult result = clientResponse->result;
653 if (result == OC_STACK_OK)
655 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
658 rep = parseGetSetCallback(clientResponse);
660 catch(OC::OCException& e)
666 std::thread exec(context->callback, serverHeaderOptions, rep, result);
668 return OC_STACK_DELETE_TRANSACTION;
671 OCStackResult InProcClientWrapper::GetResourceRepresentation(
672 const OCDevAddr& devAddr,
673 const std::string& resourceUri,
674 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
675 OCConnectivityType connectivityType,
676 GetCallback& callback, QualityOfService QoS)
680 return OC_STACK_INVALID_PARAM;
682 OCStackResult result;
683 ClientCallbackContext::GetContext* ctx =
684 new ClientCallbackContext::GetContext(callback);
685 OCCallbackData cbdata;
686 cbdata.context = static_cast<void*>(ctx),
687 cbdata.cb = getResourceCallback;
688 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
691 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
693 auto cLock = m_csdkLock.lock();
697 std::lock_guard<std::recursive_mutex> lock(*cLock);
698 OCHeaderOption options[MAX_HEADER_OPTIONS];
700 result = OCDoResource(
701 nullptr, OC_REST_GET,
705 static_cast<OCQualityOfService>(QoS),
707 assembleHeaderOptions(options, headerOptions),
708 headerOptions.size());
713 result = OC_STACK_ERROR;
719 OCStackApplicationResult setResourceCallback(void* ctx,
720 OCDoHandle /*handle*/,
721 OCClientResponse* clientResponse)
723 ClientCallbackContext::SetContext* context =
724 static_cast<ClientCallbackContext::SetContext*>(ctx);
725 OCRepresentation attrs;
726 HeaderOptions serverHeaderOptions;
728 OCStackResult result = clientResponse->result;
729 if (OC_STACK_OK == result ||
730 OC_STACK_RESOURCE_CREATED == result ||
731 OC_STACK_RESOURCE_DELETED == result ||
732 OC_STACK_RESOURCE_CHANGED == result)
734 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
737 attrs = parseGetSetCallback(clientResponse);
739 catch(OC::OCException& e)
745 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
747 return OC_STACK_DELETE_TRANSACTION;
750 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
751 const QueryParamsMap& queryParams)
755 if (uri.back() == '/')
757 uri.resize(uri.size() - 1);
761 ostringstream paramsList;
762 if (queryParams.size() > 0)
767 for (auto& param : queryParams)
769 paramsList << param.first <<'='<<param.second<<';';
772 std::string queryString = paramsList.str();
774 if (queryString.empty())
779 if (queryString.back() == ';')
781 queryString.resize(queryString.size() - 1);
784 std::string ret = uri + queryString;
788 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
789 const QueryParamsList& queryParams)
793 if (uri.back() == '/')
795 uri.resize(uri.size() - 1);
799 ostringstream paramsList;
800 if (queryParams.size() > 0)
805 for (auto& param : queryParams)
807 for (auto& paramList : param.second)
809 paramsList << param.first << '=' << paramList;
810 if (paramList != param.second.back())
818 std::string queryString = paramsList.str();
820 if (queryString.empty())
825 if (queryString.back() == ';')
827 queryString.resize(queryString.size() - 1);
830 std::string ret = uri + queryString;
834 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
836 MessageContainer ocInfo;
837 ocInfo.addRepresentation(rep);
838 for(const OCRepresentation& r : rep.getChildren())
840 ocInfo.addRepresentation(r);
843 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
846 OCStackResult InProcClientWrapper::PostResourceRepresentation(
847 const OCDevAddr& devAddr,
848 const std::string& uri,
849 const OCRepresentation& rep,
850 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
851 OCConnectivityType connectivityType,
852 PostCallback& callback, QualityOfService QoS)
856 return OC_STACK_INVALID_PARAM;
858 OCStackResult result;
859 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
860 OCCallbackData cbdata;
861 cbdata.context = static_cast<void*>(ctx),
862 cbdata.cb = setResourceCallback;
863 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
866 std::string url = assembleSetResourceUri(uri, queryParams);
868 auto cLock = m_csdkLock.lock();
872 std::lock_guard<std::recursive_mutex> lock(*cLock);
873 OCHeaderOption options[MAX_HEADER_OPTIONS];
875 result = OCDoResource(nullptr, OC_REST_POST,
876 url.c_str(), &devAddr,
877 assembleSetResourcePayload(rep),
879 static_cast<OCQualityOfService>(QoS),
881 assembleHeaderOptions(options, headerOptions),
882 headerOptions.size());
887 result = OC_STACK_ERROR;
893 OCStackResult InProcClientWrapper::PutResourceRepresentation(
894 const OCDevAddr& devAddr,
895 const std::string& uri,
896 const OCRepresentation& rep,
897 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
898 PutCallback& callback, QualityOfService QoS)
902 return OC_STACK_INVALID_PARAM;
904 OCStackResult result;
905 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
906 OCCallbackData cbdata;
907 cbdata.context = static_cast<void*>(ctx),
908 cbdata.cb = setResourceCallback;
909 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
912 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
914 auto cLock = m_csdkLock.lock();
918 std::lock_guard<std::recursive_mutex> lock(*cLock);
920 OCHeaderOption options[MAX_HEADER_OPTIONS];
922 result = OCDoResource(&handle, OC_REST_PUT,
923 url.c_str(), &devAddr,
924 assembleSetResourcePayload(rep),
926 static_cast<OCQualityOfService>(QoS),
928 assembleHeaderOptions(options, headerOptions),
929 headerOptions.size());
934 result = OC_STACK_ERROR;
940 OCStackApplicationResult deleteResourceCallback(void* ctx,
941 OCDoHandle /*handle*/,
942 OCClientResponse* clientResponse)
944 ClientCallbackContext::DeleteContext* context =
945 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
946 HeaderOptions serverHeaderOptions;
948 if (clientResponse->result == OC_STACK_OK)
950 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
952 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
954 return OC_STACK_DELETE_TRANSACTION;
957 OCStackResult InProcClientWrapper::DeleteResource(
958 const OCDevAddr& devAddr,
959 const std::string& uri,
960 const HeaderOptions& headerOptions,
961 OCConnectivityType connectivityType,
962 DeleteCallback& callback,
963 QualityOfService /*QoS*/)
967 return OC_STACK_INVALID_PARAM;
969 OCStackResult result;
970 ClientCallbackContext::DeleteContext* ctx =
971 new ClientCallbackContext::DeleteContext(callback);
972 OCCallbackData cbdata;
973 cbdata.context = static_cast<void*>(ctx),
974 cbdata.cb = deleteResourceCallback;
975 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
978 auto cLock = m_csdkLock.lock();
982 OCHeaderOption options[MAX_HEADER_OPTIONS];
984 std::lock_guard<std::recursive_mutex> lock(*cLock);
986 result = OCDoResource(nullptr, OC_REST_DELETE,
987 uri.c_str(), &devAddr,
990 static_cast<OCQualityOfService>(m_cfg.QoS),
992 assembleHeaderOptions(options, headerOptions),
993 headerOptions.size());
998 result = OC_STACK_ERROR;
1004 OCStackApplicationResult observeResourceCallback(void* ctx,
1005 OCDoHandle /*handle*/,
1006 OCClientResponse* clientResponse)
1008 ClientCallbackContext::ObserveContext* context =
1009 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1010 OCRepresentation attrs;
1011 HeaderOptions serverHeaderOptions;
1012 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1013 OCStackResult result = clientResponse->result;
1014 if (clientResponse->result == OC_STACK_OK)
1016 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1019 attrs = parseGetSetCallback(clientResponse);
1021 catch(OC::OCException& e)
1026 std::thread exec(context->callback, serverHeaderOptions, attrs,
1027 result, sequenceNumber);
1030 return OC_STACK_KEEP_TRANSACTION;
1033 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1034 const OCDevAddr& devAddr,
1035 const std::string& uri,
1036 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1037 ObserveCallback& callback, QualityOfService QoS)
1041 return OC_STACK_INVALID_PARAM;
1043 OCStackResult result;
1045 ClientCallbackContext::ObserveContext* ctx =
1046 new ClientCallbackContext::ObserveContext(callback);
1047 OCCallbackData cbdata;
1048 cbdata.context = static_cast<void*>(ctx),
1049 cbdata.cb = observeResourceCallback;
1050 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1054 if (observeType == ObserveType::Observe)
1056 method = OC_REST_OBSERVE;
1058 else if (observeType == ObserveType::ObserveAll)
1060 method = OC_REST_OBSERVE_ALL;
1064 method = OC_REST_OBSERVE_ALL;
1067 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1069 auto cLock = m_csdkLock.lock();
1073 std::lock_guard<std::recursive_mutex> lock(*cLock);
1074 OCHeaderOption options[MAX_HEADER_OPTIONS];
1076 result = OCDoResource(handle, method,
1077 url.c_str(), &devAddr,
1080 static_cast<OCQualityOfService>(QoS),
1082 assembleHeaderOptions(options, headerOptions),
1083 headerOptions.size());
1088 return OC_STACK_ERROR;
1094 OCStackResult InProcClientWrapper::CancelObserveResource(
1096 const std::string& /*host*/,
1097 const std::string& /*uri*/,
1098 const HeaderOptions& headerOptions,
1099 QualityOfService QoS)
1101 OCStackResult result;
1102 auto cLock = m_csdkLock.lock();
1106 std::lock_guard<std::recursive_mutex> lock(*cLock);
1107 OCHeaderOption options[MAX_HEADER_OPTIONS];
1109 result = OCCancel(handle,
1110 static_cast<OCQualityOfService>(QoS),
1111 assembleHeaderOptions(options, headerOptions),
1112 headerOptions.size());
1116 result = OC_STACK_ERROR;
1122 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1123 OCDoHandle /*handle*/,
1124 OCClientResponse* clientResponse)
1126 ClientCallbackContext::SubscribePresenceContext* context =
1127 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1130 * This a hack while we rethink presence subscription.
1132 std::string url = clientResponse->devAddr.addr;
1134 std::thread exec(context->callback, clientResponse->result,
1135 clientResponse->sequenceNumber, url);
1139 return OC_STACK_KEEP_TRANSACTION;
1142 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1143 const std::string& host, const std::string& resourceType,
1144 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1146 if (!presenceHandler)
1148 return OC_STACK_INVALID_PARAM;
1151 ClientCallbackContext::SubscribePresenceContext* ctx =
1152 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1153 OCCallbackData cbdata;
1154 cbdata.context = static_cast<void*>(ctx),
1155 cbdata.cb = subscribePresenceCallback;
1156 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1159 auto cLock = m_csdkLock.lock();
1161 std::ostringstream os;
1162 os << host << OC_RSRVD_PRESENCE_URI;
1164 if (!resourceType.empty())
1166 os << "?rt=" << resourceType;
1172 return OC_STACK_ERROR;
1175 return OCDoResource(handle, OC_REST_PRESENCE,
1176 os.str().c_str(), nullptr,
1177 nullptr, connectivityType,
1178 OC_LOW_QOS, &cbdata, NULL, 0);
1181 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1183 OCStackResult result;
1184 auto cLock = m_csdkLock.lock();
1188 std::lock_guard<std::recursive_mutex> lock(*cLock);
1189 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1193 result = OC_STACK_ERROR;
1200 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1201 const std::string& host,
1202 const std::vector<std::string>& di,
1203 OCConnectivityType connectivityType,
1204 ObserveCallback& callback)
1208 return OC_STACK_INVALID_PARAM;
1210 OCStackResult result;
1212 ClientCallbackContext::ObserveContext* ctx =
1213 new ClientCallbackContext::ObserveContext(callback);
1214 OCCallbackData cbdata;
1215 cbdata.context = static_cast<void*>(ctx),
1216 cbdata.cb = observeResourceCallback;
1217 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1219 auto cLock = m_csdkLock.lock();
1223 std::lock_guard<std::recursive_mutex> lock(*cLock);
1225 std::ostringstream os;
1226 os << host << OCF_RSRVD_DEVICE_PRESENCE_URI;
1227 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1228 std::string url = assembleSetResourceUri(os.str(), queryParams);
1230 result = OCDoResource(handle, OC_REST_OBSERVE,
1231 url.c_str(), nullptr,
1232 nullptr, connectivityType,
1233 OC_LOW_QOS, &cbdata,
1239 result = OC_STACK_ERROR;
1246 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1252 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1253 const HeaderOptions& headerOptions)
1257 if ( headerOptions.size() == 0)
1262 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1264 options[i] = OCHeaderOption();
1265 options[i].protocolID = OC_COAP_ID;
1266 options[i].optionID = it->getOptionID();
1267 options[i].optionLength = it->getOptionData().length() + 1;
1268 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1275 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1282 OCDPDev_t* result = new OCDPDev_t(*dev);
1283 result->prm = new OCPrm_t[dev->prmLen];
1284 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1285 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1288 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1292 dpList.push_back(cloneDevice(list));
1297 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1298 GetDirectPairedCallback& callback)
1300 if (!callback || 0 == waittime)
1302 return OC_STACK_INVALID_PARAM;
1305 OCStackResult result = OC_STACK_ERROR;
1306 const OCDPDev_t *list = nullptr;
1307 PairedDevices dpDeviceList;
1309 auto cLock = m_csdkLock.lock();
1313 std::lock_guard<std::recursive_mutex> lock(*cLock);
1315 list = OCDiscoverDirectPairingDevices(waittime);
1318 result = OC_STACK_NO_RESOURCE;
1319 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1323 convert(list, dpDeviceList);
1324 std::thread exec(callback, dpDeviceList);
1326 result = OC_STACK_OK;
1331 result = OC_STACK_ERROR;
1337 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1341 return OC_STACK_INVALID_PARAM;
1344 OCStackResult result = OC_STACK_ERROR;
1345 const OCDPDev_t *list = nullptr;
1346 PairedDevices dpDeviceList;
1348 auto cLock = m_csdkLock.lock();
1352 std::lock_guard<std::recursive_mutex> lock(*cLock);
1354 list = OCGetDirectPairedDevices();
1357 result = OC_STACK_NO_RESOURCE;
1358 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1362 convert(list, dpDeviceList);
1363 std::thread exec(callback, dpDeviceList);
1365 result = OC_STACK_OK;
1370 result = OC_STACK_ERROR;
1376 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1377 OCStackResult result)
1380 ClientCallbackContext::DirectPairingContext* context =
1381 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1383 std::thread exec(context->callback, cloneDevice(peer), result);
1387 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1388 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1390 if (!peer || !callback)
1392 oclog() << "Invalid parameters" << std::flush;
1393 return OC_STACK_INVALID_PARAM;
1396 OCStackResult result = OC_STACK_ERROR;
1397 ClientCallbackContext::DirectPairingContext* context =
1398 new ClientCallbackContext::DirectPairingContext(callback);
1400 auto cLock = m_csdkLock.lock();
1403 std::lock_guard<std::recursive_mutex> lock(*cLock);
1404 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1405 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1410 result = OC_STACK_ERROR;