1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "InProcClientWrapper.h"
24 #include "OCPlatform.h"
25 #include "OCResource.h"
26 #include "ocpayload.h"
27 #include <OCSerialization.h>
32 InProcClientWrapper::InProcClientWrapper(
33 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
34 : m_threadRun(false), m_csdkLock(csdkLock),
37 // if the config type is server, we ought to never get called. If the config type
38 // is both, we count on the server to run the thread and do the initialize
40 if (m_cfg.mode == ModeType::Client)
42 OCTransportFlags serverFlags =
43 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
44 OCTransportFlags clientFlags =
45 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
46 OCStackResult result = OCInit1(OC_CLIENT, serverFlags, clientFlags);
48 if (OC_STACK_OK != result)
50 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
54 m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
58 InProcClientWrapper::~InProcClientWrapper()
60 if (m_threadRun && m_listeningThread.joinable())
63 m_listeningThread.join();
66 // only stop if we are the ones who actually called 'init'. We are counting
67 // on the server to do the stop.
68 if (m_cfg.mode == ModeType::Client)
74 void InProcClientWrapper::listeningFunc()
79 auto cLock = m_csdkLock.lock();
82 std::lock_guard<std::recursive_mutex> lock(*cLock);
87 result = OC_STACK_ERROR;
90 if (result != OC_STACK_OK)
92 // TODO: do something with result if failed?
95 // To minimize CPU utilization we may wish to do this with sleep
96 std::this_thread::sleep_for(std::chrono::milliseconds(10));
100 OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
102 if (clientResponse->payload == nullptr ||
104 clientResponse->payload->type != PAYLOAD_TYPE_DEVICE &&
105 clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM &&
106 clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
110 //OCPayloadDestroy(clientResponse->payload);
111 return OCRepresentation();
115 oc.setPayload(clientResponse->payload);
116 //OCPayloadDestroy(clientResponse->payload);
118 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
119 if (it == oc.representations().end())
121 return OCRepresentation();
124 // first one is considered the root, everything else is considered a child of this one.
125 OCRepresentation root = *it;
126 root.setDevAddr(clientResponse->devAddr);
127 root.setUri(clientResponse->resourceUri);
130 std::for_each(it, oc.representations().end(),
131 [&root](const OCRepresentation& repItr)
132 {root.addChild(repItr);});
137 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
138 OCClientResponse* clientResponse)
140 ClientCallbackContext::ListenContext* context =
141 static_cast<ClientCallbackContext::ListenContext*>(ctx);
143 if (clientResponse->result != OC_STACK_OK)
145 oclog() << "listenCallback(): failed to create resource. clientResponse: "
146 << clientResponse->result
149 return OC_STACK_KEEP_TRANSACTION;
152 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
154 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
156 return OC_STACK_KEEP_TRANSACTION;
159 auto clientWrapper = context->clientWrapper.lock();
163 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
165 return OC_STACK_KEEP_TRANSACTION;
170 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
171 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
172 // loop to ensure valid construction of all resources
174 for(auto resource : container.Resources())
176 std::thread exec(context->callback, resource);
180 catch (std::exception &e)
182 oclog() << "Exception in listCallback, ignoring response: "
183 << e.what() << std::flush;
187 return OC_STACK_KEEP_TRANSACTION;
190 OCStackApplicationResult listenErrorCallback(void* ctx, OCDoHandle /*handle*/,
191 OCClientResponse* clientResponse)
193 if (!ctx || !clientResponse)
195 return OC_STACK_KEEP_TRANSACTION;
198 ClientCallbackContext::ListenErrorContext* context =
199 static_cast<ClientCallbackContext::ListenErrorContext*>(ctx);
202 return OC_STACK_KEEP_TRANSACTION;
205 OCStackResult result = clientResponse->result;
206 if (result == OC_STACK_OK)
208 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
210 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
212 return OC_STACK_KEEP_TRANSACTION;
215 auto clientWrapper = context->clientWrapper.lock();
219 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
221 return OC_STACK_KEEP_TRANSACTION;
224 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
225 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
226 // loop to ensure valid construction of all resources
227 for (auto resource : container.Resources())
229 std::thread exec(context->callback, resource);
232 return OC_STACK_KEEP_TRANSACTION;
235 std::string resourceURI = clientResponse->resourceUri;
236 std::thread exec(context->errorCallback, resourceURI, result);
238 return OC_STACK_KEEP_TRANSACTION;
241 OCStackResult InProcClientWrapper::ListenForResource(
242 const std::string& serviceUrl,
243 const std::string& resourceType,
244 OCConnectivityType connectivityType,
245 FindCallback& callback, QualityOfService QoS)
249 return OC_STACK_INVALID_PARAM;
252 OCStackResult result;
253 ostringstream resourceUri;
254 resourceUri << serviceUrl << resourceType;
256 ClientCallbackContext::ListenContext* context =
257 new ClientCallbackContext::ListenContext(callback, shared_from_this());
258 OCCallbackData cbdata;
259 cbdata.context = static_cast<void*>(context),
260 cbdata.cb = listenCallback;
261 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
263 auto cLock = m_csdkLock.lock();
266 std::lock_guard<std::recursive_mutex> lock(*cLock);
267 result = OCDoResource(nullptr, OC_REST_DISCOVER,
268 resourceUri.str().c_str(),
269 nullptr, nullptr, connectivityType,
270 static_cast<OCQualityOfService>(QoS),
277 result = OC_STACK_ERROR;
282 OCStackResult InProcClientWrapper::ListenErrorForResource(
283 const std::string& serviceUrl,
284 const std::string& resourceType,
285 OCConnectivityType connectivityType,
286 FindCallback& callback, FindErrorCallback& errorCallback,
287 QualityOfService QoS)
291 return OC_STACK_INVALID_PARAM;
294 ostringstream resourceUri;
295 resourceUri << serviceUrl << resourceType;
297 ClientCallbackContext::ListenErrorContext* context =
298 new ClientCallbackContext::ListenErrorContext(callback, errorCallback,
302 return OC_STACK_ERROR;
305 OCCallbackData cbdata(
306 static_cast<void*>(context),
308 [](void* c){delete static_cast<ClientCallbackContext::ListenErrorContext*>(c);}
311 OCStackResult result;
312 auto cLock = m_csdkLock.lock();
315 std::lock_guard<std::recursive_mutex> lock(*cLock);
316 result = OCDoResource(nullptr, OC_REST_DISCOVER,
317 resourceUri.str().c_str(),
318 nullptr, nullptr, connectivityType,
319 static_cast<OCQualityOfService>(QoS),
326 result = OC_STACK_ERROR;
331 OCStackApplicationResult listenCallback2(void* ctx, OCDoHandle /*handle*/,
332 OCClientResponse* clientResponse)
334 ClientCallbackContext::ListenContext2* context =
335 static_cast<ClientCallbackContext::ListenContext2*>(ctx);
337 if (clientResponse->result != OC_STACK_OK)
339 oclog() << "listenCallback2(): failed to create resource. clientResponse: "
340 << clientResponse->result
343 return OC_STACK_KEEP_TRANSACTION;
346 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
348 oclog() << "listenCallback2(): clientResponse payload was null or the wrong type"
350 return OC_STACK_KEEP_TRANSACTION;
353 auto clientWrapper = context->clientWrapper.lock();
357 oclog() << "listenCallback2(): failed to get a shared_ptr to the client wrapper"
359 return OC_STACK_KEEP_TRANSACTION;
364 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
365 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
367 std::thread exec(context->callback, container.Resources());
370 catch (std::exception &e)
372 oclog() << "Exception in listCallback2, ignoring response: "
373 << e.what() << std::flush;
377 return OC_STACK_KEEP_TRANSACTION;
380 OCStackResult InProcClientWrapper::ListenForResource2(
381 const std::string& serviceUrl,
382 const std::string& resourceType,
383 OCConnectivityType connectivityType,
384 FindResListCallback& callback, QualityOfService QoS)
388 return OC_STACK_INVALID_PARAM;
391 OCStackResult result;
392 ostringstream resourceUri;
393 resourceUri << serviceUrl << resourceType;
395 ClientCallbackContext::ListenContext2* context =
396 new ClientCallbackContext::ListenContext2(callback, shared_from_this());
397 OCCallbackData cbdata;
398 cbdata.context = static_cast<void*>(context),
399 cbdata.cb = listenCallback2;
400 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext2*)c;};
402 auto cLock = m_csdkLock.lock();
405 std::lock_guard<std::recursive_mutex> lock(*cLock);
406 result = OCDoResource(nullptr, OC_REST_DISCOVER,
407 resourceUri.str().c_str(),
408 nullptr, nullptr, connectivityType,
409 static_cast<OCQualityOfService>(QoS),
416 result = OC_STACK_ERROR;
422 OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
423 OCClientResponse* clientResponse)
425 ClientCallbackContext::MQTopicContext* context =
426 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
428 if (!clientResponse || !context)
430 return OC_STACK_DELETE_TRANSACTION;
433 std::string resourceURI = clientResponse->resourceUri;
434 if (clientResponse->result != OC_STACK_OK)
436 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
437 << clientResponse->result
440 std::thread exec(context->callback, clientResponse->result,
441 resourceURI, nullptr);
444 return OC_STACK_DELETE_TRANSACTION;
447 auto clientWrapper = context->clientWrapper.lock();
450 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
452 return OC_STACK_DELETE_TRANSACTION;
457 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
458 (OCRepPayload *) clientResponse->payload);
460 // loop to ensure valid construction of all resources
461 for (auto resource : container.Resources())
463 std::thread exec(context->callback, clientResponse->result,
464 resourceURI, resource);
468 catch (std::exception &e)
470 oclog() << "Exception in listCallback, ignoring response: "
471 << e.what() << std::flush;
474 return OC_STACK_DELETE_TRANSACTION;
477 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
478 const std::string& resourceUri,
479 const QueryParamsMap& queryParams,
480 const HeaderOptions& headerOptions,
481 MQTopicCallback& callback,
482 QualityOfService QoS)
484 oclog() << "ListenForMQTopic()" << std::flush;
488 return OC_STACK_INVALID_PARAM;
491 ClientCallbackContext::MQTopicContext* context =
492 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
493 OCCallbackData cbdata;
494 cbdata.context = static_cast<void*>(context),
495 cbdata.cb = listenMQCallback;
496 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
498 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
500 OCStackResult result = OC_STACK_ERROR;
501 auto cLock = m_csdkLock.lock();
504 std::lock_guard<std::recursive_mutex> lock(*cLock);
505 OCHeaderOption options[MAX_HEADER_OPTIONS];
506 result = OCDoResource(
507 nullptr, OC_REST_GET,
511 static_cast<OCQualityOfService>(QoS),
513 assembleHeaderOptions(options, headerOptions),
514 headerOptions.size());
525 OCStackApplicationResult listenDeviceCallback(void* ctx,
526 OCDoHandle /*handle*/,
527 OCClientResponse* clientResponse)
529 ClientCallbackContext::DeviceListenContext* context =
530 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
534 OCRepresentation rep = parseGetSetCallback(clientResponse);
535 std::thread exec(context->callback, rep);
538 catch(OC::OCException& e)
540 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
541 <<e.what() <<std::flush;
544 return OC_STACK_KEEP_TRANSACTION;
547 OCStackResult InProcClientWrapper::ListenForDevice(
548 const std::string& serviceUrl,
549 const std::string& deviceURI,
550 OCConnectivityType connectivityType,
551 FindDeviceCallback& callback,
552 QualityOfService QoS)
556 return OC_STACK_INVALID_PARAM;
558 OCStackResult result;
559 ostringstream deviceUri;
560 deviceUri << serviceUrl << deviceURI;
562 ClientCallbackContext::DeviceListenContext* context =
563 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
564 OCCallbackData cbdata;
566 cbdata.context = static_cast<void*>(context),
567 cbdata.cb = listenDeviceCallback;
568 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
570 auto cLock = m_csdkLock.lock();
573 std::lock_guard<std::recursive_mutex> lock(*cLock);
574 result = OCDoResource(nullptr, OC_REST_DISCOVER,
575 deviceUri.str().c_str(),
576 nullptr, nullptr, connectivityType,
577 static_cast<OCQualityOfService>(QoS),
584 result = OC_STACK_ERROR;
589 void parseServerHeaderOptions(OCClientResponse* clientResponse,
590 HeaderOptions& serverHeaderOptions)
594 // Parse header options from server
596 std::string optionData;
598 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
600 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
601 optionData = reinterpret_cast<const char*>
602 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
603 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
604 serverHeaderOptions.push_back(headerOption);
609 // clientResponse is invalid
610 // TODO check proper logging
611 std::cout << " Invalid response " << std::endl;
616 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
617 OCClientResponse* clientResponse)
619 ClientCallbackContext::MQTopicContext* context =
620 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
621 HeaderOptions serverHeaderOptions;
623 if (!clientResponse || !context)
625 return OC_STACK_DELETE_TRANSACTION;
628 std::string createdUri;
629 bool isLocationOption = false;
630 OCStackResult result = clientResponse->result;
631 if (OC_STACK_OK == result ||
632 OC_STACK_RESOURCE_CREATED == result)
634 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
636 for (auto headerOption : serverHeaderOptions)
638 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
641 createdUri += headerOption.getOptionData();
642 if (!isLocationOption)
644 isLocationOption = true;
650 if (!isLocationOption)
652 createdUri = std::string(clientResponse->resourceUri);
655 auto clientWrapper = context->clientWrapper.lock();
659 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
661 return OC_STACK_DELETE_TRANSACTION;
666 if (OC_STACK_OK == result ||
667 OC_STACK_RESOURCE_CREATED == result)
669 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
671 for (auto resource : container.Resources())
673 std::thread exec(context->callback, result,
681 std::thread exec(context->callback, result,
687 catch (std::exception &e)
689 oclog() << "Exception in createMQTopicCallback, ignoring response: "
690 << e.what() << std::flush;
692 return OC_STACK_DELETE_TRANSACTION;
695 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
696 const OCDevAddr& devAddr,
697 const std::string& uri,
698 const OCRepresentation& rep,
699 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
700 MQTopicCallback& callback, QualityOfService QoS)
704 return OC_STACK_INVALID_PARAM;
706 OCStackResult result;
707 ClientCallbackContext::MQTopicContext* ctx =
708 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
709 OCCallbackData cbdata;
710 cbdata.context = static_cast<void*>(ctx),
711 cbdata.cb = createMQTopicCallback;
712 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
714 std::string url = assembleSetResourceUri(uri, queryParams);
716 auto cLock = m_csdkLock.lock();
720 std::lock_guard<std::recursive_mutex> lock(*cLock);
721 OCHeaderOption options[MAX_HEADER_OPTIONS];
723 result = OCDoResource(nullptr, OC_REST_PUT,
724 url.c_str(), &devAddr,
725 assembleSetResourcePayload(rep),
727 static_cast<OCQualityOfService>(QoS),
729 assembleHeaderOptions(options, headerOptions),
730 headerOptions.size());
735 result = OC_STACK_ERROR;
741 OCStackApplicationResult getResourceCallback(void* ctx,
742 OCDoHandle /*handle*/,
743 OCClientResponse* clientResponse)
745 ClientCallbackContext::GetContext* context =
746 static_cast<ClientCallbackContext::GetContext*>(ctx);
748 OCRepresentation rep;
749 HeaderOptions serverHeaderOptions;
750 OCStackResult result = clientResponse->result;
752 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
755 rep = parseGetSetCallback(clientResponse);
757 catch(OC::OCException& e)
762 std::thread exec(context->callback, serverHeaderOptions, rep, result);
764 return OC_STACK_DELETE_TRANSACTION;
767 OCStackResult InProcClientWrapper::GetResourceRepresentation(
768 const OCDevAddr& devAddr,
769 const std::string& resourceUri,
770 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
771 OCConnectivityType connectivityType,
772 GetCallback& callback, QualityOfService QoS)
776 return OC_STACK_INVALID_PARAM;
778 OCStackResult result;
779 ClientCallbackContext::GetContext* ctx =
780 new ClientCallbackContext::GetContext(callback);
781 OCCallbackData cbdata;
782 cbdata.context = static_cast<void*>(ctx),
783 cbdata.cb = getResourceCallback;
784 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
787 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
789 auto cLock = m_csdkLock.lock();
793 std::lock_guard<std::recursive_mutex> lock(*cLock);
794 OCHeaderOption options[MAX_HEADER_OPTIONS];
796 result = OCDoResource(
797 nullptr, OC_REST_GET,
801 static_cast<OCQualityOfService>(QoS),
803 assembleHeaderOptions(options, headerOptions),
804 headerOptions.size());
809 result = OC_STACK_ERROR;
815 OCStackApplicationResult setResourceCallback(void* ctx,
816 OCDoHandle /*handle*/,
817 OCClientResponse* clientResponse)
819 ClientCallbackContext::SetContext* context =
820 static_cast<ClientCallbackContext::SetContext*>(ctx);
821 OCRepresentation attrs;
822 HeaderOptions serverHeaderOptions;
824 OCStackResult result = clientResponse->result;
826 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
829 attrs = parseGetSetCallback(clientResponse);
831 catch(OC::OCException& e)
836 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
838 return OC_STACK_DELETE_TRANSACTION;
841 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
842 const QueryParamsMap& queryParams)
846 if (uri.back() == '/')
848 uri.resize(uri.size() - 1);
852 ostringstream paramsList;
853 if (queryParams.size() > 0)
858 for (auto& param : queryParams)
860 paramsList << param.first <<'='<<param.second<<';';
863 std::string queryString = paramsList.str();
865 if (queryString.empty())
870 if (queryString.back() == ';')
872 queryString.resize(queryString.size() - 1);
875 std::string ret = uri + queryString;
879 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
880 const QueryParamsList& queryParams)
884 if (uri.back() == '/')
886 uri.resize(uri.size() - 1);
890 ostringstream paramsList;
891 if (queryParams.size() > 0)
896 for (auto& param : queryParams)
898 for (auto& paramList : param.second)
900 paramsList << param.first << '=' << paramList << ';';
904 std::string queryString = paramsList.str();
906 if (queryString.empty())
911 if (queryString.back() == ';')
913 queryString.resize(queryString.size() - 1);
916 std::string ret = uri + queryString;
920 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
922 MessageContainer ocInfo;
923 ocInfo.addRepresentation(rep);
924 for(const OCRepresentation& r : rep.getChildren())
926 ocInfo.addRepresentation(r);
929 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
932 OCStackResult InProcClientWrapper::PostResourceRepresentation(
933 const OCDevAddr& devAddr,
934 const std::string& uri,
935 const OCRepresentation& rep,
936 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
937 OCConnectivityType connectivityType,
938 PostCallback& callback, QualityOfService QoS)
942 return OC_STACK_INVALID_PARAM;
944 OCStackResult result;
945 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
946 OCCallbackData cbdata;
947 cbdata.context = static_cast<void*>(ctx),
948 cbdata.cb = setResourceCallback;
949 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
952 std::string url = assembleSetResourceUri(uri, queryParams);
954 auto cLock = m_csdkLock.lock();
958 std::lock_guard<std::recursive_mutex> lock(*cLock);
959 OCHeaderOption options[MAX_HEADER_OPTIONS];
961 result = OCDoResource(nullptr, OC_REST_POST,
962 url.c_str(), &devAddr,
963 assembleSetResourcePayload(rep),
965 static_cast<OCQualityOfService>(QoS),
967 assembleHeaderOptions(options, headerOptions),
968 headerOptions.size());
973 result = OC_STACK_ERROR;
979 OCStackResult InProcClientWrapper::PutResourceRepresentation(
980 const OCDevAddr& devAddr,
981 const std::string& uri,
982 const OCRepresentation& rep,
983 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
984 PutCallback& callback, QualityOfService QoS)
988 return OC_STACK_INVALID_PARAM;
990 OCStackResult result;
991 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
992 OCCallbackData cbdata;
993 cbdata.context = static_cast<void*>(ctx),
994 cbdata.cb = setResourceCallback;
995 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
998 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1000 auto cLock = m_csdkLock.lock();
1004 std::lock_guard<std::recursive_mutex> lock(*cLock);
1006 OCHeaderOption options[MAX_HEADER_OPTIONS];
1008 result = OCDoResource(&handle, OC_REST_PUT,
1009 url.c_str(), &devAddr,
1010 assembleSetResourcePayload(rep),
1012 static_cast<OCQualityOfService>(QoS),
1014 assembleHeaderOptions(options, headerOptions),
1015 headerOptions.size());
1020 result = OC_STACK_ERROR;
1026 OCStackApplicationResult deleteResourceCallback(void* ctx,
1027 OCDoHandle /*handle*/,
1028 OCClientResponse* clientResponse)
1030 ClientCallbackContext::DeleteContext* context =
1031 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
1032 HeaderOptions serverHeaderOptions;
1034 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1036 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
1038 return OC_STACK_DELETE_TRANSACTION;
1041 OCStackResult InProcClientWrapper::DeleteResource(
1042 const OCDevAddr& devAddr,
1043 const std::string& uri,
1044 const HeaderOptions& headerOptions,
1045 OCConnectivityType connectivityType,
1046 DeleteCallback& callback,
1047 QualityOfService /*QoS*/)
1051 return OC_STACK_INVALID_PARAM;
1053 OCStackResult result;
1054 ClientCallbackContext::DeleteContext* ctx =
1055 new ClientCallbackContext::DeleteContext(callback);
1056 OCCallbackData cbdata;
1057 cbdata.context = static_cast<void*>(ctx),
1058 cbdata.cb = deleteResourceCallback;
1059 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
1062 auto cLock = m_csdkLock.lock();
1066 OCHeaderOption options[MAX_HEADER_OPTIONS];
1068 std::lock_guard<std::recursive_mutex> lock(*cLock);
1070 result = OCDoResource(nullptr, OC_REST_DELETE,
1071 uri.c_str(), &devAddr,
1074 static_cast<OCQualityOfService>(m_cfg.QoS),
1076 assembleHeaderOptions(options, headerOptions),
1077 headerOptions.size());
1082 result = OC_STACK_ERROR;
1088 OCStackApplicationResult observeResourceCallback(void* ctx,
1089 OCDoHandle /*handle*/,
1090 OCClientResponse* clientResponse)
1092 ClientCallbackContext::ObserveContext* context =
1093 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1094 OCRepresentation attrs;
1095 HeaderOptions serverHeaderOptions;
1096 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1097 OCStackResult result = clientResponse->result;
1099 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1102 attrs = parseGetSetCallback(clientResponse);
1104 catch(OC::OCException& e)
1109 std::thread exec(context->callback, serverHeaderOptions, attrs,
1110 result, sequenceNumber);
1112 if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
1114 return OC_STACK_DELETE_TRANSACTION;
1117 return OC_STACK_KEEP_TRANSACTION;
1120 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1121 const OCDevAddr& devAddr,
1122 const std::string& uri,
1123 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1124 ObserveCallback& callback, QualityOfService QoS)
1128 return OC_STACK_INVALID_PARAM;
1130 OCStackResult result;
1132 ClientCallbackContext::ObserveContext* ctx =
1133 new ClientCallbackContext::ObserveContext(callback);
1134 OCCallbackData cbdata;
1135 cbdata.context = static_cast<void*>(ctx),
1136 cbdata.cb = observeResourceCallback;
1137 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1141 if (observeType == ObserveType::Observe)
1143 method = OC_REST_OBSERVE;
1145 else if (observeType == ObserveType::ObserveAll)
1147 method = OC_REST_OBSERVE_ALL;
1151 method = OC_REST_OBSERVE_ALL;
1154 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1156 auto cLock = m_csdkLock.lock();
1160 std::lock_guard<std::recursive_mutex> lock(*cLock);
1161 OCHeaderOption options[MAX_HEADER_OPTIONS];
1163 result = OCDoResource(handle, method,
1164 url.c_str(), &devAddr,
1167 static_cast<OCQualityOfService>(QoS),
1169 assembleHeaderOptions(options, headerOptions),
1170 headerOptions.size());
1175 return OC_STACK_ERROR;
1181 OCStackResult InProcClientWrapper::CancelObserveResource(
1183 const std::string& /*host*/,
1184 const std::string& /*uri*/,
1185 const HeaderOptions& headerOptions,
1186 QualityOfService QoS)
1188 OCStackResult result;
1189 auto cLock = m_csdkLock.lock();
1193 std::lock_guard<std::recursive_mutex> lock(*cLock);
1194 OCHeaderOption options[MAX_HEADER_OPTIONS];
1196 result = OCCancel(handle,
1197 static_cast<OCQualityOfService>(QoS),
1198 assembleHeaderOptions(options, headerOptions),
1199 headerOptions.size());
1203 result = OC_STACK_ERROR;
1209 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1210 OCDoHandle /*handle*/,
1211 OCClientResponse* clientResponse)
1213 ClientCallbackContext::SubscribePresenceContext* context =
1214 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1217 * This a hack while we rethink presence subscription.
1219 std::string url = clientResponse->devAddr.addr;
1221 std::thread exec(context->callback, clientResponse->result,
1222 clientResponse->sequenceNumber, url);
1226 return OC_STACK_KEEP_TRANSACTION;
1229 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1230 const std::string& host, const std::string& resourceType,
1231 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1233 if (!presenceHandler)
1235 return OC_STACK_INVALID_PARAM;
1238 ClientCallbackContext::SubscribePresenceContext* ctx =
1239 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1240 OCCallbackData cbdata;
1241 cbdata.context = static_cast<void*>(ctx),
1242 cbdata.cb = subscribePresenceCallback;
1243 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1246 auto cLock = m_csdkLock.lock();
1248 std::ostringstream os;
1249 os << host << OC_RSRVD_PRESENCE_URI;
1251 if (!resourceType.empty())
1253 os << "?rt=" << resourceType;
1259 return OC_STACK_ERROR;
1262 return OCDoResource(handle, OC_REST_PRESENCE,
1263 os.str().c_str(), nullptr,
1264 nullptr, connectivityType,
1265 OC_LOW_QOS, &cbdata, NULL, 0);
1268 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1270 OCStackResult result;
1271 auto cLock = m_csdkLock.lock();
1275 std::lock_guard<std::recursive_mutex> lock(*cLock);
1276 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1280 result = OC_STACK_ERROR;
1287 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1288 const std::string& host,
1289 const std::vector<std::string>& di,
1290 OCConnectivityType connectivityType,
1291 ObserveCallback& callback)
1295 return OC_STACK_INVALID_PARAM;
1297 OCStackResult result;
1299 ClientCallbackContext::ObserveContext* ctx =
1300 new ClientCallbackContext::ObserveContext(callback);
1301 OCCallbackData cbdata;
1302 cbdata.context = static_cast<void*>(ctx),
1303 cbdata.cb = observeResourceCallback;
1304 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1306 auto cLock = m_csdkLock.lock();
1310 std::lock_guard<std::recursive_mutex> lock(*cLock);
1312 std::ostringstream os;
1313 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1314 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1315 std::string url = assembleSetResourceUri(os.str(), queryParams);
1317 result = OCDoResource(handle, OC_REST_OBSERVE,
1318 url.c_str(), nullptr,
1319 nullptr, connectivityType,
1320 OC_LOW_QOS, &cbdata,
1326 result = OC_STACK_ERROR;
1333 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1339 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1340 const HeaderOptions& headerOptions)
1344 if ( headerOptions.size() == 0)
1349 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1351 options[i] = OCHeaderOption();
1352 options[i].protocolID = OC_COAP_ID;
1353 options[i].optionID = it->getOptionID();
1354 options[i].optionLength = it->getOptionData().length() + 1;
1355 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1362 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1369 OCDPDev_t* result = new OCDPDev_t(*dev);
1370 result->prm = new OCPrm_t[dev->prmLen];
1371 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1372 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1375 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1379 dpList.push_back(cloneDevice(list));
1384 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1385 GetDirectPairedCallback& callback)
1387 if (!callback || 0 == waittime)
1389 return OC_STACK_INVALID_PARAM;
1392 OCStackResult result = OC_STACK_ERROR;
1393 const OCDPDev_t *list = nullptr;
1394 PairedDevices dpDeviceList;
1396 auto cLock = m_csdkLock.lock();
1400 std::lock_guard<std::recursive_mutex> lock(*cLock);
1402 list = OCDiscoverDirectPairingDevices(waittime);
1405 result = OC_STACK_NO_RESOURCE;
1406 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1410 convert(list, dpDeviceList);
1411 std::thread exec(callback, dpDeviceList);
1413 result = OC_STACK_OK;
1418 result = OC_STACK_ERROR;
1424 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1428 return OC_STACK_INVALID_PARAM;
1431 OCStackResult result = OC_STACK_ERROR;
1432 const OCDPDev_t *list = nullptr;
1433 PairedDevices dpDeviceList;
1435 auto cLock = m_csdkLock.lock();
1439 std::lock_guard<std::recursive_mutex> lock(*cLock);
1441 list = OCGetDirectPairedDevices();
1444 result = OC_STACK_NO_RESOURCE;
1445 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1449 convert(list, dpDeviceList);
1450 std::thread exec(callback, dpDeviceList);
1452 result = OC_STACK_OK;
1457 result = OC_STACK_ERROR;
1463 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1464 OCStackResult result)
1467 ClientCallbackContext::DirectPairingContext* context =
1468 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1470 std::thread exec(context->callback, cloneDevice(peer), result);
1474 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1475 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1477 if (!peer || !callback)
1479 oclog() << "Invalid parameters" << std::flush;
1480 return OC_STACK_INVALID_PARAM;
1483 OCStackResult result = OC_STACK_ERROR;
1484 ClientCallbackContext::DirectPairingContext* context =
1485 new ClientCallbackContext::DirectPairingContext(callback);
1487 auto cLock = m_csdkLock.lock();
1490 std::lock_guard<std::recursive_mutex> lock(*cLock);
1491 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1492 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1497 result = OC_STACK_ERROR;