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::MQTopicContext* context =
333 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
335 if (!clientResponse || !context)
337 return OC_STACK_DELETE_TRANSACTION;
340 if (clientResponse->result != OC_STACK_OK)
342 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
343 << clientResponse->result
346 std::thread exec(context->callback, clientResponse->result,
347 clientResponse->resourceUri, nullptr);
350 return OC_STACK_DELETE_TRANSACTION;
353 auto clientWrapper = context->clientWrapper.lock();
356 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
358 return OC_STACK_DELETE_TRANSACTION;
362 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
363 (OCRepPayload *) clientResponse->payload);
365 // loop to ensure valid construction of all resources
366 for (auto resource : container.Resources())
368 std::thread exec(context->callback, clientResponse->result,
369 clientResponse->resourceUri, resource);
373 catch (std::exception &e){
374 oclog() << "Exception in listCallback, ignoring response: "
375 << e.what() << std::flush;
378 return OC_STACK_DELETE_TRANSACTION;
381 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
382 const std::string& resourceUri,
383 const QueryParamsMap& queryParams,
384 const HeaderOptions& headerOptions,
385 MQTopicCallback& callback,
386 QualityOfService QoS)
388 oclog() << "ListenForMQTopic()" << std::flush;
392 return OC_STACK_INVALID_PARAM;
395 ClientCallbackContext::MQTopicContext* context =
396 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
397 OCCallbackData cbdata;
398 cbdata.context = static_cast<void*>(context),
399 cbdata.cb = listenMQCallback;
400 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
402 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
404 OCStackResult result = OC_STACK_ERROR;
405 auto cLock = m_csdkLock.lock();
408 std::lock_guard<std::recursive_mutex> lock(*cLock);
409 OCHeaderOption options[MAX_HEADER_OPTIONS];
410 result = OCDoResource(
411 nullptr, OC_REST_GET,
415 static_cast<OCQualityOfService>(QoS),
417 assembleHeaderOptions(options, headerOptions),
418 headerOptions.size());
429 OCStackApplicationResult listenDeviceCallback(void* ctx,
430 OCDoHandle /*handle*/,
431 OCClientResponse* clientResponse)
433 ClientCallbackContext::DeviceListenContext* context =
434 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
438 OCRepresentation rep = parseGetSetCallback(clientResponse);
439 std::thread exec(context->callback, rep);
442 catch(OC::OCException& e)
444 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
445 <<e.what() <<std::flush;
448 return OC_STACK_KEEP_TRANSACTION;
451 OCStackResult InProcClientWrapper::ListenForDevice(
452 const std::string& serviceUrl,
453 const std::string& deviceURI,
454 OCConnectivityType connectivityType,
455 FindDeviceCallback& callback,
456 QualityOfService QoS)
460 return OC_STACK_INVALID_PARAM;
462 OCStackResult result;
463 ostringstream deviceUri;
464 deviceUri << serviceUrl << deviceURI;
466 ClientCallbackContext::DeviceListenContext* context =
467 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
468 OCCallbackData cbdata;
470 cbdata.context = static_cast<void*>(context),
471 cbdata.cb = listenDeviceCallback;
472 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
474 auto cLock = m_csdkLock.lock();
477 std::lock_guard<std::recursive_mutex> lock(*cLock);
478 result = OCDoResource(nullptr, OC_REST_DISCOVER,
479 deviceUri.str().c_str(),
480 nullptr, nullptr, connectivityType,
481 static_cast<OCQualityOfService>(QoS),
488 result = OC_STACK_ERROR;
493 void parseServerHeaderOptions(OCClientResponse* clientResponse,
494 HeaderOptions& serverHeaderOptions)
498 // Parse header options from server
500 std::string optionData;
502 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
504 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
505 optionData = reinterpret_cast<const char*>
506 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
507 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
508 serverHeaderOptions.push_back(headerOption);
513 // clientResponse is invalid
514 // TODO check proper logging
515 std::cout << " Invalid response " << std::endl;
520 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
521 OCClientResponse* clientResponse)
523 ClientCallbackContext::MQTopicContext* context =
524 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
525 HeaderOptions serverHeaderOptions;
527 if (!clientResponse || !context)
529 return OC_STACK_DELETE_TRANSACTION;
532 std::string createdUri;
533 bool isLocationOption = false;
534 OCStackResult result = clientResponse->result;
535 if (OC_STACK_OK == result ||
536 OC_STACK_RESOURCE_CREATED == result)
538 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
540 for (auto headerOption : serverHeaderOptions)
542 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
545 createdUri += headerOption.getOptionData();
546 if (!isLocationOption)
548 isLocationOption = true;
554 if (!isLocationOption)
556 createdUri = clientResponse->resourceUri;
559 auto clientWrapper = context->clientWrapper.lock();
563 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
565 return OC_STACK_DELETE_TRANSACTION;
569 if (OC_STACK_OK == result ||
570 OC_STACK_RESOURCE_CREATED == result)
572 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
574 for (auto resource : container.Resources())
576 std::thread exec(context->callback, result, createdUri, resource);
582 std::thread exec(context->callback, result, createdUri, nullptr);
586 catch (std::exception &e){
587 oclog() << "Exception in createMQTopicCallback, ignoring response: "
588 << e.what() << std::flush;
590 return OC_STACK_DELETE_TRANSACTION;
593 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
594 const OCDevAddr& devAddr,
595 const std::string& uri,
596 const OCRepresentation& rep,
597 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
598 MQTopicCallback& callback, QualityOfService QoS)
602 return OC_STACK_INVALID_PARAM;
604 OCStackResult result;
605 ClientCallbackContext::MQTopicContext* ctx =
606 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
607 OCCallbackData cbdata;
608 cbdata.context = static_cast<void*>(ctx),
609 cbdata.cb = createMQTopicCallback;
610 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
612 std::string url = assembleSetResourceUri(uri, queryParams);
614 auto cLock = m_csdkLock.lock();
618 std::lock_guard<std::recursive_mutex> lock(*cLock);
619 OCHeaderOption options[MAX_HEADER_OPTIONS];
621 result = OCDoResource(nullptr, OC_REST_PUT,
622 url.c_str(), &devAddr,
623 assembleSetResourcePayload(rep),
625 static_cast<OCQualityOfService>(QoS),
627 assembleHeaderOptions(options, headerOptions),
628 headerOptions.size());
633 result = OC_STACK_ERROR;
639 OCStackApplicationResult getResourceCallback(void* ctx,
640 OCDoHandle /*handle*/,
641 OCClientResponse* clientResponse)
643 ClientCallbackContext::GetContext* context =
644 static_cast<ClientCallbackContext::GetContext*>(ctx);
646 OCRepresentation rep;
647 HeaderOptions serverHeaderOptions;
648 OCStackResult result = clientResponse->result;
649 if (result == OC_STACK_OK)
651 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
654 rep = parseGetSetCallback(clientResponse);
656 catch(OC::OCException& e)
662 std::thread exec(context->callback, serverHeaderOptions, rep, result);
664 return OC_STACK_DELETE_TRANSACTION;
667 OCStackResult InProcClientWrapper::GetResourceRepresentation(
668 const OCDevAddr& devAddr,
669 const std::string& resourceUri,
670 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
671 OCConnectivityType connectivityType,
672 GetCallback& callback, QualityOfService QoS)
676 return OC_STACK_INVALID_PARAM;
678 OCStackResult result;
679 ClientCallbackContext::GetContext* ctx =
680 new ClientCallbackContext::GetContext(callback);
681 OCCallbackData cbdata;
682 cbdata.context = static_cast<void*>(ctx),
683 cbdata.cb = getResourceCallback;
684 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
687 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
689 auto cLock = m_csdkLock.lock();
693 std::lock_guard<std::recursive_mutex> lock(*cLock);
694 OCHeaderOption options[MAX_HEADER_OPTIONS];
696 result = OCDoResource(
697 nullptr, OC_REST_GET,
701 static_cast<OCQualityOfService>(QoS),
703 assembleHeaderOptions(options, headerOptions),
704 headerOptions.size());
709 result = OC_STACK_ERROR;
715 OCStackApplicationResult setResourceCallback(void* ctx,
716 OCDoHandle /*handle*/,
717 OCClientResponse* clientResponse)
719 ClientCallbackContext::SetContext* context =
720 static_cast<ClientCallbackContext::SetContext*>(ctx);
721 OCRepresentation attrs;
722 HeaderOptions serverHeaderOptions;
724 OCStackResult result = clientResponse->result;
725 if (OC_STACK_OK == result ||
726 OC_STACK_RESOURCE_CREATED == result ||
727 OC_STACK_RESOURCE_DELETED == result ||
728 OC_STACK_RESOURCE_CHANGED == result)
730 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
733 attrs = parseGetSetCallback(clientResponse);
735 catch(OC::OCException& e)
741 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
743 return OC_STACK_DELETE_TRANSACTION;
746 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
747 const QueryParamsMap& queryParams)
751 if (uri.back() == '/')
753 uri.resize(uri.size() - 1);
757 ostringstream paramsList;
758 if (queryParams.size() > 0)
763 for (auto& param : queryParams)
765 paramsList << param.first <<'='<<param.second<<';';
768 std::string queryString = paramsList.str();
770 if (queryString.empty())
775 if (queryString.back() == ';')
777 queryString.resize(queryString.size() - 1);
780 std::string ret = uri + queryString;
784 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
785 const QueryParamsList& queryParams)
789 if (uri.back() == '/')
791 uri.resize(uri.size() - 1);
795 ostringstream paramsList;
796 if (queryParams.size() > 0)
801 for (auto& param : queryParams)
803 for (auto& paramList : param.second)
805 paramsList << param.first << '=' << paramList << ';';
809 std::string queryString = paramsList.str();
811 if (queryString.empty())
816 if (queryString.back() == ';')
818 queryString.resize(queryString.size() - 1);
821 std::string ret = uri + queryString;
825 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
827 MessageContainer ocInfo;
828 ocInfo.addRepresentation(rep);
829 for(const OCRepresentation& r : rep.getChildren())
831 ocInfo.addRepresentation(r);
834 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
837 OCStackResult InProcClientWrapper::PostResourceRepresentation(
838 const OCDevAddr& devAddr,
839 const std::string& uri,
840 const OCRepresentation& rep,
841 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
842 OCConnectivityType connectivityType,
843 PostCallback& callback, QualityOfService QoS)
847 return OC_STACK_INVALID_PARAM;
849 OCStackResult result;
850 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
851 OCCallbackData cbdata;
852 cbdata.context = static_cast<void*>(ctx),
853 cbdata.cb = setResourceCallback;
854 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
857 std::string url = assembleSetResourceUri(uri, queryParams);
859 auto cLock = m_csdkLock.lock();
863 std::lock_guard<std::recursive_mutex> lock(*cLock);
864 OCHeaderOption options[MAX_HEADER_OPTIONS];
866 result = OCDoResource(nullptr, OC_REST_POST,
867 url.c_str(), &devAddr,
868 assembleSetResourcePayload(rep),
870 static_cast<OCQualityOfService>(QoS),
872 assembleHeaderOptions(options, headerOptions),
873 headerOptions.size());
878 result = OC_STACK_ERROR;
884 OCStackResult InProcClientWrapper::PutResourceRepresentation(
885 const OCDevAddr& devAddr,
886 const std::string& uri,
887 const OCRepresentation& rep,
888 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
889 PutCallback& callback, QualityOfService QoS)
893 return OC_STACK_INVALID_PARAM;
895 OCStackResult result;
896 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
897 OCCallbackData cbdata;
898 cbdata.context = static_cast<void*>(ctx),
899 cbdata.cb = setResourceCallback;
900 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
903 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
905 auto cLock = m_csdkLock.lock();
909 std::lock_guard<std::recursive_mutex> lock(*cLock);
911 OCHeaderOption options[MAX_HEADER_OPTIONS];
913 result = OCDoResource(&handle, OC_REST_PUT,
914 url.c_str(), &devAddr,
915 assembleSetResourcePayload(rep),
917 static_cast<OCQualityOfService>(QoS),
919 assembleHeaderOptions(options, headerOptions),
920 headerOptions.size());
925 result = OC_STACK_ERROR;
931 OCStackApplicationResult deleteResourceCallback(void* ctx,
932 OCDoHandle /*handle*/,
933 OCClientResponse* clientResponse)
935 ClientCallbackContext::DeleteContext* context =
936 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
937 HeaderOptions serverHeaderOptions;
939 if (clientResponse->result == OC_STACK_OK)
941 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
943 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
945 return OC_STACK_DELETE_TRANSACTION;
948 OCStackResult InProcClientWrapper::DeleteResource(
949 const OCDevAddr& devAddr,
950 const std::string& uri,
951 const HeaderOptions& headerOptions,
952 OCConnectivityType connectivityType,
953 DeleteCallback& callback,
954 QualityOfService /*QoS*/)
958 return OC_STACK_INVALID_PARAM;
960 OCStackResult result;
961 ClientCallbackContext::DeleteContext* ctx =
962 new ClientCallbackContext::DeleteContext(callback);
963 OCCallbackData cbdata;
964 cbdata.context = static_cast<void*>(ctx),
965 cbdata.cb = deleteResourceCallback;
966 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
969 auto cLock = m_csdkLock.lock();
973 OCHeaderOption options[MAX_HEADER_OPTIONS];
975 std::lock_guard<std::recursive_mutex> lock(*cLock);
977 result = OCDoResource(nullptr, OC_REST_DELETE,
978 uri.c_str(), &devAddr,
981 static_cast<OCQualityOfService>(m_cfg.QoS),
983 assembleHeaderOptions(options, headerOptions),
984 headerOptions.size());
989 result = OC_STACK_ERROR;
995 OCStackApplicationResult observeResourceCallback(void* ctx,
996 OCDoHandle /*handle*/,
997 OCClientResponse* clientResponse)
999 ClientCallbackContext::ObserveContext* context =
1000 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1001 OCRepresentation attrs;
1002 HeaderOptions serverHeaderOptions;
1003 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1004 OCStackResult result = clientResponse->result;
1005 if (clientResponse->result == OC_STACK_OK)
1007 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1010 attrs = parseGetSetCallback(clientResponse);
1012 catch(OC::OCException& e)
1017 std::thread exec(context->callback, serverHeaderOptions, attrs,
1018 result, sequenceNumber);
1021 return OC_STACK_KEEP_TRANSACTION;
1024 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1025 const OCDevAddr& devAddr,
1026 const std::string& uri,
1027 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1028 ObserveCallback& callback, QualityOfService QoS)
1032 return OC_STACK_INVALID_PARAM;
1034 OCStackResult result;
1036 ClientCallbackContext::ObserveContext* ctx =
1037 new ClientCallbackContext::ObserveContext(callback);
1038 OCCallbackData cbdata;
1039 cbdata.context = static_cast<void*>(ctx),
1040 cbdata.cb = observeResourceCallback;
1041 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1045 if (observeType == ObserveType::Observe)
1047 method = OC_REST_OBSERVE;
1049 else if (observeType == ObserveType::ObserveAll)
1051 method = OC_REST_OBSERVE_ALL;
1055 method = OC_REST_OBSERVE_ALL;
1058 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1060 auto cLock = m_csdkLock.lock();
1064 std::lock_guard<std::recursive_mutex> lock(*cLock);
1065 OCHeaderOption options[MAX_HEADER_OPTIONS];
1067 result = OCDoResource(handle, method,
1068 url.c_str(), &devAddr,
1071 static_cast<OCQualityOfService>(QoS),
1073 assembleHeaderOptions(options, headerOptions),
1074 headerOptions.size());
1079 return OC_STACK_ERROR;
1085 OCStackResult InProcClientWrapper::CancelObserveResource(
1087 const std::string& /*host*/,
1088 const std::string& /*uri*/,
1089 const HeaderOptions& headerOptions,
1090 QualityOfService QoS)
1092 OCStackResult result;
1093 auto cLock = m_csdkLock.lock();
1097 std::lock_guard<std::recursive_mutex> lock(*cLock);
1098 OCHeaderOption options[MAX_HEADER_OPTIONS];
1100 result = OCCancel(handle,
1101 static_cast<OCQualityOfService>(QoS),
1102 assembleHeaderOptions(options, headerOptions),
1103 headerOptions.size());
1107 result = OC_STACK_ERROR;
1113 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1114 OCDoHandle /*handle*/,
1115 OCClientResponse* clientResponse)
1117 ClientCallbackContext::SubscribePresenceContext* context =
1118 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1121 * This a hack while we rethink presence subscription.
1123 std::string url = clientResponse->devAddr.addr;
1125 std::thread exec(context->callback, clientResponse->result,
1126 clientResponse->sequenceNumber, url);
1130 return OC_STACK_KEEP_TRANSACTION;
1133 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1134 const std::string& host, const std::string& resourceType,
1135 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1137 if (!presenceHandler)
1139 return OC_STACK_INVALID_PARAM;
1142 ClientCallbackContext::SubscribePresenceContext* ctx =
1143 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1144 OCCallbackData cbdata;
1145 cbdata.context = static_cast<void*>(ctx),
1146 cbdata.cb = subscribePresenceCallback;
1147 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1150 auto cLock = m_csdkLock.lock();
1152 std::ostringstream os;
1153 os << host << OC_RSRVD_PRESENCE_URI;
1155 if (!resourceType.empty())
1157 os << "?rt=" << resourceType;
1163 return OC_STACK_ERROR;
1166 return OCDoResource(handle, OC_REST_PRESENCE,
1167 os.str().c_str(), nullptr,
1168 nullptr, connectivityType,
1169 OC_LOW_QOS, &cbdata, NULL, 0);
1172 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1174 OCStackResult result;
1175 auto cLock = m_csdkLock.lock();
1179 std::lock_guard<std::recursive_mutex> lock(*cLock);
1180 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1184 result = OC_STACK_ERROR;
1191 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1192 const std::string& host,
1193 const std::vector<std::string>& di,
1194 OCConnectivityType connectivityType,
1195 ObserveCallback& callback)
1199 return OC_STACK_INVALID_PARAM;
1201 OCStackResult result;
1203 ClientCallbackContext::ObserveContext* ctx =
1204 new ClientCallbackContext::ObserveContext(callback);
1205 OCCallbackData cbdata;
1206 cbdata.context = static_cast<void*>(ctx),
1207 cbdata.cb = observeResourceCallback;
1208 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1210 auto cLock = m_csdkLock.lock();
1214 std::lock_guard<std::recursive_mutex> lock(*cLock);
1216 std::ostringstream os;
1217 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1218 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1219 std::string url = assembleSetResourceUri(os.str(), queryParams);
1221 result = OCDoResource(handle, OC_REST_OBSERVE,
1222 url.c_str(), nullptr,
1223 nullptr, connectivityType,
1224 OC_LOW_QOS, &cbdata,
1230 result = OC_STACK_ERROR;
1237 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1243 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1244 const HeaderOptions& headerOptions)
1248 if ( headerOptions.size() == 0)
1253 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1255 options[i] = OCHeaderOption();
1256 options[i].protocolID = OC_COAP_ID;
1257 options[i].optionID = it->getOptionID();
1258 options[i].optionLength = it->getOptionData().length() + 1;
1259 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1266 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1273 OCDPDev_t* result = new OCDPDev_t(*dev);
1274 result->prm = new OCPrm_t[dev->prmLen];
1275 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1276 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1279 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1283 dpList.push_back(cloneDevice(list));
1288 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1289 GetDirectPairedCallback& callback)
1291 if (!callback || 0 == waittime)
1293 return OC_STACK_INVALID_PARAM;
1296 OCStackResult result = OC_STACK_ERROR;
1297 const OCDPDev_t *list = nullptr;
1298 PairedDevices dpDeviceList;
1300 auto cLock = m_csdkLock.lock();
1304 std::lock_guard<std::recursive_mutex> lock(*cLock);
1306 list = OCDiscoverDirectPairingDevices(waittime);
1309 result = OC_STACK_NO_RESOURCE;
1310 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1314 convert(list, dpDeviceList);
1315 std::thread exec(callback, dpDeviceList);
1317 result = OC_STACK_OK;
1322 result = OC_STACK_ERROR;
1328 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1332 return OC_STACK_INVALID_PARAM;
1335 OCStackResult result = OC_STACK_ERROR;
1336 const OCDPDev_t *list = nullptr;
1337 PairedDevices dpDeviceList;
1339 auto cLock = m_csdkLock.lock();
1343 std::lock_guard<std::recursive_mutex> lock(*cLock);
1345 list = OCGetDirectPairedDevices();
1348 result = OC_STACK_NO_RESOURCE;
1349 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1353 convert(list, dpDeviceList);
1354 std::thread exec(callback, dpDeviceList);
1356 result = OC_STACK_OK;
1361 result = OC_STACK_ERROR;
1367 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1368 OCStackResult result)
1371 ClientCallbackContext::DirectPairingContext* context =
1372 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1374 std::thread exec(context->callback, cloneDevice(peer), result);
1378 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1379 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1381 if (!peer || !callback)
1383 oclog() << "Invalid parameters" << std::flush;
1384 return OC_STACK_INVALID_PARAM;
1387 OCStackResult result = OC_STACK_ERROR;
1388 ClientCallbackContext::DirectPairingContext* context =
1389 new ClientCallbackContext::DirectPairingContext(callback);
1391 auto cLock = m_csdkLock.lock();
1394 std::lock_guard<std::recursive_mutex> lock(*cLock);
1395 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1396 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1401 result = OC_STACK_ERROR;