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 std::string(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 std::string(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 = std::string(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,
589 std::thread exec(context->callback, result,
595 catch (std::exception &e)
597 oclog() << "Exception in createMQTopicCallback, ignoring response: "
598 << e.what() << std::flush;
600 return OC_STACK_DELETE_TRANSACTION;
603 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
604 const OCDevAddr& devAddr,
605 const std::string& uri,
606 const OCRepresentation& rep,
607 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
608 MQTopicCallback& callback, QualityOfService QoS)
612 return OC_STACK_INVALID_PARAM;
614 OCStackResult result;
615 ClientCallbackContext::MQTopicContext* ctx =
616 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
617 OCCallbackData cbdata;
618 cbdata.context = static_cast<void*>(ctx),
619 cbdata.cb = createMQTopicCallback;
620 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
622 std::string url = assembleSetResourceUri(uri, queryParams);
624 auto cLock = m_csdkLock.lock();
628 std::lock_guard<std::recursive_mutex> lock(*cLock);
629 OCHeaderOption options[MAX_HEADER_OPTIONS];
631 result = OCDoResource(nullptr, OC_REST_PUT,
632 url.c_str(), &devAddr,
633 assembleSetResourcePayload(rep),
635 static_cast<OCQualityOfService>(QoS),
637 assembleHeaderOptions(options, headerOptions),
638 headerOptions.size());
643 result = OC_STACK_ERROR;
649 OCStackApplicationResult getResourceCallback(void* ctx,
650 OCDoHandle /*handle*/,
651 OCClientResponse* clientResponse)
653 ClientCallbackContext::GetContext* context =
654 static_cast<ClientCallbackContext::GetContext*>(ctx);
656 OCRepresentation rep;
657 HeaderOptions serverHeaderOptions;
658 OCStackResult result = clientResponse->result;
659 if (result == OC_STACK_OK)
661 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
664 rep = parseGetSetCallback(clientResponse);
666 catch(OC::OCException& e)
672 std::thread exec(context->callback, serverHeaderOptions, rep, result);
674 return OC_STACK_DELETE_TRANSACTION;
677 OCStackResult InProcClientWrapper::GetResourceRepresentation(
678 const OCDevAddr& devAddr,
679 const std::string& resourceUri,
680 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
681 OCConnectivityType connectivityType,
682 GetCallback& callback, QualityOfService QoS)
686 return OC_STACK_INVALID_PARAM;
688 OCStackResult result;
689 ClientCallbackContext::GetContext* ctx =
690 new ClientCallbackContext::GetContext(callback);
691 OCCallbackData cbdata;
692 cbdata.context = static_cast<void*>(ctx),
693 cbdata.cb = getResourceCallback;
694 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
697 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
699 auto cLock = m_csdkLock.lock();
703 std::lock_guard<std::recursive_mutex> lock(*cLock);
704 OCHeaderOption options[MAX_HEADER_OPTIONS];
706 result = OCDoResource(
707 nullptr, OC_REST_GET,
711 static_cast<OCQualityOfService>(QoS),
713 assembleHeaderOptions(options, headerOptions),
714 headerOptions.size());
719 result = OC_STACK_ERROR;
725 OCStackApplicationResult setResourceCallback(void* ctx,
726 OCDoHandle /*handle*/,
727 OCClientResponse* clientResponse)
729 ClientCallbackContext::SetContext* context =
730 static_cast<ClientCallbackContext::SetContext*>(ctx);
731 OCRepresentation attrs;
732 HeaderOptions serverHeaderOptions;
734 OCStackResult result = clientResponse->result;
735 if (OC_STACK_OK == result ||
736 OC_STACK_RESOURCE_CREATED == result ||
737 OC_STACK_RESOURCE_DELETED == result ||
738 OC_STACK_RESOURCE_CHANGED == result)
740 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
743 attrs = parseGetSetCallback(clientResponse);
745 catch(OC::OCException& e)
751 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
753 return OC_STACK_DELETE_TRANSACTION;
756 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
757 const QueryParamsMap& queryParams)
761 if (uri.back() == '/')
763 uri.resize(uri.size() - 1);
767 ostringstream paramsList;
768 if (queryParams.size() > 0)
773 for (auto& param : queryParams)
775 paramsList << param.first <<'='<<param.second<<';';
778 std::string queryString = paramsList.str();
780 if (queryString.empty())
785 if (queryString.back() == ';')
787 queryString.resize(queryString.size() - 1);
790 std::string ret = uri + queryString;
794 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
795 const QueryParamsList& queryParams)
799 if (uri.back() == '/')
801 uri.resize(uri.size() - 1);
805 ostringstream paramsList;
806 if (queryParams.size() > 0)
811 for (auto& param : queryParams)
813 for (auto& paramList : param.second)
815 paramsList << param.first << '=' << paramList << ';';
819 std::string queryString = paramsList.str();
821 if (queryString.empty())
826 if (queryString.back() == ';')
828 queryString.resize(queryString.size() - 1);
831 std::string ret = uri + queryString;
835 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
837 MessageContainer ocInfo;
838 ocInfo.addRepresentation(rep);
839 for(const OCRepresentation& r : rep.getChildren())
841 ocInfo.addRepresentation(r);
844 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
847 OCStackResult InProcClientWrapper::PostResourceRepresentation(
848 const OCDevAddr& devAddr,
849 const std::string& uri,
850 const OCRepresentation& rep,
851 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
852 OCConnectivityType connectivityType,
853 PostCallback& callback, QualityOfService QoS)
857 return OC_STACK_INVALID_PARAM;
859 OCStackResult result;
860 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
861 OCCallbackData cbdata;
862 cbdata.context = static_cast<void*>(ctx),
863 cbdata.cb = setResourceCallback;
864 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
867 std::string url = assembleSetResourceUri(uri, queryParams);
869 auto cLock = m_csdkLock.lock();
873 std::lock_guard<std::recursive_mutex> lock(*cLock);
874 OCHeaderOption options[MAX_HEADER_OPTIONS];
876 result = OCDoResource(nullptr, OC_REST_POST,
877 url.c_str(), &devAddr,
878 assembleSetResourcePayload(rep),
880 static_cast<OCQualityOfService>(QoS),
882 assembleHeaderOptions(options, headerOptions),
883 headerOptions.size());
888 result = OC_STACK_ERROR;
894 OCStackResult InProcClientWrapper::PutResourceRepresentation(
895 const OCDevAddr& devAddr,
896 const std::string& uri,
897 const OCRepresentation& rep,
898 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
899 PutCallback& callback, QualityOfService QoS)
903 return OC_STACK_INVALID_PARAM;
905 OCStackResult result;
906 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
907 OCCallbackData cbdata;
908 cbdata.context = static_cast<void*>(ctx),
909 cbdata.cb = setResourceCallback;
910 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
913 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
915 auto cLock = m_csdkLock.lock();
919 std::lock_guard<std::recursive_mutex> lock(*cLock);
921 OCHeaderOption options[MAX_HEADER_OPTIONS];
923 result = OCDoResource(&handle, OC_REST_PUT,
924 url.c_str(), &devAddr,
925 assembleSetResourcePayload(rep),
927 static_cast<OCQualityOfService>(QoS),
929 assembleHeaderOptions(options, headerOptions),
930 headerOptions.size());
935 result = OC_STACK_ERROR;
941 OCStackApplicationResult deleteResourceCallback(void* ctx,
942 OCDoHandle /*handle*/,
943 OCClientResponse* clientResponse)
945 ClientCallbackContext::DeleteContext* context =
946 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
947 HeaderOptions serverHeaderOptions;
949 if (clientResponse->result == OC_STACK_OK)
951 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
953 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
955 return OC_STACK_DELETE_TRANSACTION;
958 OCStackResult InProcClientWrapper::DeleteResource(
959 const OCDevAddr& devAddr,
960 const std::string& uri,
961 const HeaderOptions& headerOptions,
962 OCConnectivityType connectivityType,
963 DeleteCallback& callback,
964 QualityOfService /*QoS*/)
968 return OC_STACK_INVALID_PARAM;
970 OCStackResult result;
971 ClientCallbackContext::DeleteContext* ctx =
972 new ClientCallbackContext::DeleteContext(callback);
973 OCCallbackData cbdata;
974 cbdata.context = static_cast<void*>(ctx),
975 cbdata.cb = deleteResourceCallback;
976 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
979 auto cLock = m_csdkLock.lock();
983 OCHeaderOption options[MAX_HEADER_OPTIONS];
985 std::lock_guard<std::recursive_mutex> lock(*cLock);
987 result = OCDoResource(nullptr, OC_REST_DELETE,
988 uri.c_str(), &devAddr,
991 static_cast<OCQualityOfService>(m_cfg.QoS),
993 assembleHeaderOptions(options, headerOptions),
994 headerOptions.size());
999 result = OC_STACK_ERROR;
1005 OCStackApplicationResult observeResourceCallback(void* ctx,
1006 OCDoHandle /*handle*/,
1007 OCClientResponse* clientResponse)
1009 ClientCallbackContext::ObserveContext* context =
1010 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1011 OCRepresentation attrs;
1012 HeaderOptions serverHeaderOptions;
1013 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1014 OCStackResult result = clientResponse->result;
1015 if (clientResponse->result == OC_STACK_OK)
1017 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1020 attrs = parseGetSetCallback(clientResponse);
1022 catch(OC::OCException& e)
1027 std::thread exec(context->callback, serverHeaderOptions, attrs,
1028 result, sequenceNumber);
1031 return OC_STACK_KEEP_TRANSACTION;
1034 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1035 const OCDevAddr& devAddr,
1036 const std::string& uri,
1037 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1038 ObserveCallback& callback, QualityOfService QoS)
1042 return OC_STACK_INVALID_PARAM;
1044 OCStackResult result;
1046 ClientCallbackContext::ObserveContext* ctx =
1047 new ClientCallbackContext::ObserveContext(callback);
1048 OCCallbackData cbdata;
1049 cbdata.context = static_cast<void*>(ctx),
1050 cbdata.cb = observeResourceCallback;
1051 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1055 if (observeType == ObserveType::Observe)
1057 method = OC_REST_OBSERVE;
1059 else if (observeType == ObserveType::ObserveAll)
1061 method = OC_REST_OBSERVE_ALL;
1065 method = OC_REST_OBSERVE_ALL;
1068 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1070 auto cLock = m_csdkLock.lock();
1074 std::lock_guard<std::recursive_mutex> lock(*cLock);
1075 OCHeaderOption options[MAX_HEADER_OPTIONS];
1077 result = OCDoResource(handle, method,
1078 url.c_str(), &devAddr,
1081 static_cast<OCQualityOfService>(QoS),
1083 assembleHeaderOptions(options, headerOptions),
1084 headerOptions.size());
1089 return OC_STACK_ERROR;
1095 OCStackResult InProcClientWrapper::CancelObserveResource(
1097 const std::string& /*host*/,
1098 const std::string& /*uri*/,
1099 const HeaderOptions& headerOptions,
1100 QualityOfService QoS)
1102 OCStackResult result;
1103 auto cLock = m_csdkLock.lock();
1107 std::lock_guard<std::recursive_mutex> lock(*cLock);
1108 OCHeaderOption options[MAX_HEADER_OPTIONS];
1110 result = OCCancel(handle,
1111 static_cast<OCQualityOfService>(QoS),
1112 assembleHeaderOptions(options, headerOptions),
1113 headerOptions.size());
1117 result = OC_STACK_ERROR;
1123 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1124 OCDoHandle /*handle*/,
1125 OCClientResponse* clientResponse)
1127 ClientCallbackContext::SubscribePresenceContext* context =
1128 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1131 * This a hack while we rethink presence subscription.
1133 std::string url = clientResponse->devAddr.addr;
1135 std::thread exec(context->callback, clientResponse->result,
1136 clientResponse->sequenceNumber, url);
1140 return OC_STACK_KEEP_TRANSACTION;
1143 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1144 const std::string& host, const std::string& resourceType,
1145 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1147 if (!presenceHandler)
1149 return OC_STACK_INVALID_PARAM;
1152 ClientCallbackContext::SubscribePresenceContext* ctx =
1153 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1154 OCCallbackData cbdata;
1155 cbdata.context = static_cast<void*>(ctx),
1156 cbdata.cb = subscribePresenceCallback;
1157 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1160 auto cLock = m_csdkLock.lock();
1162 std::ostringstream os;
1163 os << host << OC_RSRVD_PRESENCE_URI;
1165 if (!resourceType.empty())
1167 os << "?rt=" << resourceType;
1173 return OC_STACK_ERROR;
1176 return OCDoResource(handle, OC_REST_PRESENCE,
1177 os.str().c_str(), nullptr,
1178 nullptr, connectivityType,
1179 OC_LOW_QOS, &cbdata, NULL, 0);
1182 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1184 OCStackResult result;
1185 auto cLock = m_csdkLock.lock();
1189 std::lock_guard<std::recursive_mutex> lock(*cLock);
1190 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1194 result = OC_STACK_ERROR;
1201 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1202 const std::string& host,
1203 const std::vector<std::string>& di,
1204 OCConnectivityType connectivityType,
1205 ObserveCallback& callback)
1209 return OC_STACK_INVALID_PARAM;
1211 OCStackResult result;
1213 ClientCallbackContext::ObserveContext* ctx =
1214 new ClientCallbackContext::ObserveContext(callback);
1215 OCCallbackData cbdata;
1216 cbdata.context = static_cast<void*>(ctx),
1217 cbdata.cb = observeResourceCallback;
1218 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1220 auto cLock = m_csdkLock.lock();
1224 std::lock_guard<std::recursive_mutex> lock(*cLock);
1226 std::ostringstream os;
1227 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1228 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1229 std::string url = assembleSetResourceUri(os.str(), queryParams);
1231 result = OCDoResource(handle, OC_REST_OBSERVE,
1232 url.c_str(), nullptr,
1233 nullptr, connectivityType,
1234 OC_LOW_QOS, &cbdata,
1240 result = OC_STACK_ERROR;
1247 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1253 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1254 const HeaderOptions& headerOptions)
1258 if ( headerOptions.size() == 0)
1263 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1265 options[i] = OCHeaderOption();
1266 options[i].protocolID = OC_COAP_ID;
1267 options[i].optionID = it->getOptionID();
1268 options[i].optionLength = it->getOptionData().length() + 1;
1269 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1276 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1283 OCDPDev_t* result = new OCDPDev_t(*dev);
1284 result->prm = new OCPrm_t[dev->prmLen];
1285 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1286 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1289 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1293 dpList.push_back(cloneDevice(list));
1298 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1299 GetDirectPairedCallback& callback)
1301 if (!callback || 0 == waittime)
1303 return OC_STACK_INVALID_PARAM;
1306 OCStackResult result = OC_STACK_ERROR;
1307 const OCDPDev_t *list = nullptr;
1308 PairedDevices dpDeviceList;
1310 auto cLock = m_csdkLock.lock();
1314 std::lock_guard<std::recursive_mutex> lock(*cLock);
1316 list = OCDiscoverDirectPairingDevices(waittime);
1319 result = OC_STACK_NO_RESOURCE;
1320 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1324 convert(list, dpDeviceList);
1325 std::thread exec(callback, dpDeviceList);
1327 result = OC_STACK_OK;
1332 result = OC_STACK_ERROR;
1338 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1342 return OC_STACK_INVALID_PARAM;
1345 OCStackResult result = OC_STACK_ERROR;
1346 const OCDPDev_t *list = nullptr;
1347 PairedDevices dpDeviceList;
1349 auto cLock = m_csdkLock.lock();
1353 std::lock_guard<std::recursive_mutex> lock(*cLock);
1355 list = OCGetDirectPairedDevices();
1358 result = OC_STACK_NO_RESOURCE;
1359 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1363 convert(list, dpDeviceList);
1364 std::thread exec(callback, dpDeviceList);
1366 result = OC_STACK_OK;
1371 result = OC_STACK_ERROR;
1377 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1378 OCStackResult result)
1381 ClientCallbackContext::DirectPairingContext* context =
1382 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1384 std::thread exec(context->callback, cloneDevice(peer), result);
1388 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1389 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1391 if (!peer || !callback)
1393 oclog() << "Invalid parameters" << std::flush;
1394 return OC_STACK_INVALID_PARAM;
1397 OCStackResult result = OC_STACK_ERROR;
1398 ClientCallbackContext::DirectPairingContext* context =
1399 new ClientCallbackContext::DirectPairingContext(callback);
1401 auto cLock = m_csdkLock.lock();
1404 std::lock_guard<std::recursive_mutex> lock(*cLock);
1405 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1406 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1411 result = OC_STACK_ERROR;