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_REPRESENTATION
108 //OCPayloadDestroy(clientResponse->payload);
109 return OCRepresentation();
113 oc.setPayload(clientResponse->payload);
114 //OCPayloadDestroy(clientResponse->payload);
116 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
117 if (it == oc.representations().end())
119 return OCRepresentation();
122 // first one is considered the root, everything else is considered a child of this one.
123 OCRepresentation root = *it;
124 root.setDevAddr(clientResponse->devAddr);
125 root.setUri(clientResponse->resourceUri);
128 std::for_each(it, oc.representations().end(),
129 [&root](const OCRepresentation& repItr)
130 {root.addChild(repItr);});
135 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
136 OCClientResponse* clientResponse)
138 ClientCallbackContext::ListenContext* context =
139 static_cast<ClientCallbackContext::ListenContext*>(ctx);
141 if (clientResponse->result != OC_STACK_OK)
143 oclog() << "listenCallback(): failed to create resource. clientResponse: "
144 << clientResponse->result
147 return OC_STACK_KEEP_TRANSACTION;
150 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
152 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
154 return OC_STACK_KEEP_TRANSACTION;
157 auto clientWrapper = context->clientWrapper.lock();
161 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
163 return OC_STACK_KEEP_TRANSACTION;
168 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
169 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
170 // loop to ensure valid construction of all resources
172 for(auto resource : container.Resources())
174 std::thread exec(context->callback, resource);
178 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_KEEP_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 listenCallback2(void* ctx, OCDoHandle /*handle*/,
330 OCClientResponse* clientResponse)
332 ClientCallbackContext::ListenContext2* context =
333 static_cast<ClientCallbackContext::ListenContext2*>(ctx);
335 if (clientResponse->result != OC_STACK_OK)
337 oclog() << "listenCallback2(): failed to create resource. clientResponse: "
338 << clientResponse->result
341 return OC_STACK_KEEP_TRANSACTION;
344 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
346 oclog() << "listenCallback2(): clientResponse payload was null or the wrong type"
348 return OC_STACK_KEEP_TRANSACTION;
351 auto clientWrapper = context->clientWrapper.lock();
355 oclog() << "listenCallback2(): failed to get a shared_ptr to the client wrapper"
357 return OC_STACK_KEEP_TRANSACTION;
362 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
363 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
365 std::thread exec(context->callback, container.Resources());
368 catch (std::exception &e)
370 oclog() << "Exception in listCallback2, ignoring response: "
371 << e.what() << std::flush;
375 return OC_STACK_KEEP_TRANSACTION;
378 OCStackResult InProcClientWrapper::ListenForResource2(
379 const std::string& serviceUrl,
380 const std::string& resourceType,
381 OCConnectivityType connectivityType,
382 FindResListCallback& callback, QualityOfService QoS)
386 return OC_STACK_INVALID_PARAM;
389 OCStackResult result;
390 ostringstream resourceUri;
391 resourceUri << serviceUrl << resourceType;
393 ClientCallbackContext::ListenContext2* context =
394 new ClientCallbackContext::ListenContext2(callback, shared_from_this());
395 OCCallbackData cbdata;
396 cbdata.context = static_cast<void*>(context),
397 cbdata.cb = listenCallback2;
398 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext2*)c;};
400 auto cLock = m_csdkLock.lock();
403 std::lock_guard<std::recursive_mutex> lock(*cLock);
404 result = OCDoResource(nullptr, OC_REST_DISCOVER,
405 resourceUri.str().c_str(),
406 nullptr, nullptr, connectivityType,
407 static_cast<OCQualityOfService>(QoS),
414 result = OC_STACK_ERROR;
420 OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
421 OCClientResponse* clientResponse)
423 ClientCallbackContext::MQTopicContext* context =
424 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
426 if (!clientResponse || !context)
428 return OC_STACK_DELETE_TRANSACTION;
431 std::string resourceURI = clientResponse->resourceUri;
432 if (clientResponse->result != OC_STACK_OK)
434 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
435 << clientResponse->result
438 std::thread exec(context->callback, clientResponse->result,
439 resourceURI, nullptr);
442 return OC_STACK_DELETE_TRANSACTION;
445 auto clientWrapper = context->clientWrapper.lock();
448 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
450 return OC_STACK_DELETE_TRANSACTION;
455 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
456 (OCRepPayload *) clientResponse->payload);
458 // loop to ensure valid construction of all resources
459 for (auto resource : container.Resources())
461 std::thread exec(context->callback, clientResponse->result,
462 resourceURI, resource);
466 catch (std::exception &e)
468 oclog() << "Exception in listCallback, ignoring response: "
469 << e.what() << std::flush;
472 return OC_STACK_DELETE_TRANSACTION;
475 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
476 const std::string& resourceUri,
477 const QueryParamsMap& queryParams,
478 const HeaderOptions& headerOptions,
479 MQTopicCallback& callback,
480 QualityOfService QoS)
482 oclog() << "ListenForMQTopic()" << std::flush;
486 return OC_STACK_INVALID_PARAM;
489 ClientCallbackContext::MQTopicContext* context =
490 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
491 OCCallbackData cbdata;
492 cbdata.context = static_cast<void*>(context),
493 cbdata.cb = listenMQCallback;
494 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
496 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
498 OCStackResult result = OC_STACK_ERROR;
499 auto cLock = m_csdkLock.lock();
502 std::lock_guard<std::recursive_mutex> lock(*cLock);
503 OCHeaderOption options[MAX_HEADER_OPTIONS];
504 result = OCDoResource(
505 nullptr, OC_REST_GET,
509 static_cast<OCQualityOfService>(QoS),
511 assembleHeaderOptions(options, headerOptions),
512 headerOptions.size());
523 OCStackApplicationResult listenDeviceCallback(void* ctx,
524 OCDoHandle /*handle*/,
525 OCClientResponse* clientResponse)
527 ClientCallbackContext::DeviceListenContext* context =
528 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
532 OCRepresentation rep = parseGetSetCallback(clientResponse);
533 std::thread exec(context->callback, rep);
536 catch(OC::OCException& e)
538 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
539 <<e.what() <<std::flush;
542 return OC_STACK_KEEP_TRANSACTION;
545 OCStackResult InProcClientWrapper::ListenForDevice(
546 const std::string& serviceUrl,
547 const std::string& deviceURI,
548 OCConnectivityType connectivityType,
549 FindDeviceCallback& callback,
550 QualityOfService QoS)
554 return OC_STACK_INVALID_PARAM;
556 OCStackResult result;
557 ostringstream deviceUri;
558 deviceUri << serviceUrl << deviceURI;
560 ClientCallbackContext::DeviceListenContext* context =
561 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
562 OCCallbackData cbdata;
564 cbdata.context = static_cast<void*>(context),
565 cbdata.cb = listenDeviceCallback;
566 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
568 auto cLock = m_csdkLock.lock();
571 std::lock_guard<std::recursive_mutex> lock(*cLock);
572 result = OCDoResource(nullptr, OC_REST_DISCOVER,
573 deviceUri.str().c_str(),
574 nullptr, nullptr, connectivityType,
575 static_cast<OCQualityOfService>(QoS),
582 result = OC_STACK_ERROR;
587 void parseServerHeaderOptions(OCClientResponse* clientResponse,
588 HeaderOptions& serverHeaderOptions)
592 // Parse header options from server
594 std::string optionData;
596 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
598 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
599 optionData = reinterpret_cast<const char*>
600 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
601 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
602 serverHeaderOptions.push_back(headerOption);
607 // clientResponse is invalid
608 // TODO check proper logging
609 std::cout << " Invalid response " << std::endl;
614 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
615 OCClientResponse* clientResponse)
617 ClientCallbackContext::MQTopicContext* context =
618 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
619 HeaderOptions serverHeaderOptions;
621 if (!clientResponse || !context)
623 return OC_STACK_DELETE_TRANSACTION;
626 std::string createdUri;
627 bool isLocationOption = false;
628 OCStackResult result = clientResponse->result;
629 if (OC_STACK_OK == result ||
630 OC_STACK_RESOURCE_CREATED == result)
632 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
634 for (auto headerOption : serverHeaderOptions)
636 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
639 createdUri += headerOption.getOptionData();
640 if (!isLocationOption)
642 isLocationOption = true;
648 if (!isLocationOption)
650 createdUri = std::string(clientResponse->resourceUri);
653 auto clientWrapper = context->clientWrapper.lock();
657 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
659 return OC_STACK_DELETE_TRANSACTION;
664 if (OC_STACK_OK == result ||
665 OC_STACK_RESOURCE_CREATED == result)
667 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
669 for (auto resource : container.Resources())
671 std::thread exec(context->callback, result,
679 std::thread exec(context->callback, result,
685 catch (std::exception &e)
687 oclog() << "Exception in createMQTopicCallback, ignoring response: "
688 << e.what() << std::flush;
690 return OC_STACK_DELETE_TRANSACTION;
693 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
694 const OCDevAddr& devAddr,
695 const std::string& uri,
696 const OCRepresentation& rep,
697 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
698 MQTopicCallback& callback, QualityOfService QoS)
702 return OC_STACK_INVALID_PARAM;
704 OCStackResult result;
705 ClientCallbackContext::MQTopicContext* ctx =
706 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
707 OCCallbackData cbdata;
708 cbdata.context = static_cast<void*>(ctx),
709 cbdata.cb = createMQTopicCallback;
710 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
712 std::string url = assembleSetResourceUri(uri, queryParams);
714 auto cLock = m_csdkLock.lock();
718 std::lock_guard<std::recursive_mutex> lock(*cLock);
719 OCHeaderOption options[MAX_HEADER_OPTIONS];
721 result = OCDoResource(nullptr, OC_REST_PUT,
722 url.c_str(), &devAddr,
723 assembleSetResourcePayload(rep),
725 static_cast<OCQualityOfService>(QoS),
727 assembleHeaderOptions(options, headerOptions),
728 headerOptions.size());
733 result = OC_STACK_ERROR;
739 OCStackApplicationResult getResourceCallback(void* ctx,
740 OCDoHandle /*handle*/,
741 OCClientResponse* clientResponse)
743 ClientCallbackContext::GetContext* context =
744 static_cast<ClientCallbackContext::GetContext*>(ctx);
746 OCRepresentation rep;
747 HeaderOptions serverHeaderOptions;
748 OCStackResult result = clientResponse->result;
750 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
753 rep = parseGetSetCallback(clientResponse);
755 catch(OC::OCException& e)
760 std::thread exec(context->callback, serverHeaderOptions, rep, result);
762 return OC_STACK_DELETE_TRANSACTION;
765 OCStackResult InProcClientWrapper::GetResourceRepresentation(
766 const OCDevAddr& devAddr,
767 const std::string& resourceUri,
768 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
769 OCConnectivityType connectivityType,
770 GetCallback& callback, QualityOfService QoS)
774 return OC_STACK_INVALID_PARAM;
776 OCStackResult result;
777 ClientCallbackContext::GetContext* ctx =
778 new ClientCallbackContext::GetContext(callback);
779 OCCallbackData cbdata;
780 cbdata.context = static_cast<void*>(ctx),
781 cbdata.cb = getResourceCallback;
782 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
785 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
787 auto cLock = m_csdkLock.lock();
791 std::lock_guard<std::recursive_mutex> lock(*cLock);
792 OCHeaderOption options[MAX_HEADER_OPTIONS];
794 result = OCDoResource(
795 nullptr, OC_REST_GET,
799 static_cast<OCQualityOfService>(QoS),
801 assembleHeaderOptions(options, headerOptions),
802 headerOptions.size());
807 result = OC_STACK_ERROR;
813 OCStackApplicationResult setResourceCallback(void* ctx,
814 OCDoHandle /*handle*/,
815 OCClientResponse* clientResponse)
817 ClientCallbackContext::SetContext* context =
818 static_cast<ClientCallbackContext::SetContext*>(ctx);
819 OCRepresentation attrs;
820 HeaderOptions serverHeaderOptions;
822 OCStackResult result = clientResponse->result;
824 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
827 attrs = parseGetSetCallback(clientResponse);
829 catch(OC::OCException& e)
834 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
836 return OC_STACK_DELETE_TRANSACTION;
839 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
840 const QueryParamsMap& queryParams)
844 if (uri.back() == '/')
846 uri.resize(uri.size() - 1);
850 ostringstream paramsList;
851 if (queryParams.size() > 0)
856 for (auto& param : queryParams)
858 paramsList << param.first <<'='<<param.second<<';';
861 std::string queryString = paramsList.str();
863 if (queryString.empty())
868 if (queryString.back() == ';')
870 queryString.resize(queryString.size() - 1);
873 std::string ret = uri + queryString;
877 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
878 const QueryParamsList& queryParams)
882 if (uri.back() == '/')
884 uri.resize(uri.size() - 1);
888 ostringstream paramsList;
889 if (queryParams.size() > 0)
894 for (auto& param : queryParams)
896 for (auto& paramList : param.second)
898 paramsList << param.first << '=' << paramList << ';';
902 std::string queryString = paramsList.str();
904 if (queryString.empty())
909 if (queryString.back() == ';')
911 queryString.resize(queryString.size() - 1);
914 std::string ret = uri + queryString;
918 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
920 MessageContainer ocInfo;
921 ocInfo.addRepresentation(rep);
922 for(const OCRepresentation& r : rep.getChildren())
924 ocInfo.addRepresentation(r);
927 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
930 OCStackResult InProcClientWrapper::PostResourceRepresentation(
931 const OCDevAddr& devAddr,
932 const std::string& uri,
933 const OCRepresentation& rep,
934 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
935 OCConnectivityType connectivityType,
936 PostCallback& callback, QualityOfService QoS)
940 return OC_STACK_INVALID_PARAM;
942 OCStackResult result;
943 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
944 OCCallbackData cbdata;
945 cbdata.context = static_cast<void*>(ctx),
946 cbdata.cb = setResourceCallback;
947 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
950 std::string url = assembleSetResourceUri(uri, queryParams);
952 auto cLock = m_csdkLock.lock();
956 std::lock_guard<std::recursive_mutex> lock(*cLock);
957 OCHeaderOption options[MAX_HEADER_OPTIONS];
959 result = OCDoResource(nullptr, OC_REST_POST,
960 url.c_str(), &devAddr,
961 assembleSetResourcePayload(rep),
963 static_cast<OCQualityOfService>(QoS),
965 assembleHeaderOptions(options, headerOptions),
966 headerOptions.size());
971 result = OC_STACK_ERROR;
977 OCStackResult InProcClientWrapper::PutResourceRepresentation(
978 const OCDevAddr& devAddr,
979 const std::string& uri,
980 const OCRepresentation& rep,
981 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
982 PutCallback& callback, QualityOfService QoS)
986 return OC_STACK_INVALID_PARAM;
988 OCStackResult result;
989 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
990 OCCallbackData cbdata;
991 cbdata.context = static_cast<void*>(ctx),
992 cbdata.cb = setResourceCallback;
993 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
996 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
998 auto cLock = m_csdkLock.lock();
1002 std::lock_guard<std::recursive_mutex> lock(*cLock);
1004 OCHeaderOption options[MAX_HEADER_OPTIONS];
1006 result = OCDoResource(&handle, OC_REST_PUT,
1007 url.c_str(), &devAddr,
1008 assembleSetResourcePayload(rep),
1010 static_cast<OCQualityOfService>(QoS),
1012 assembleHeaderOptions(options, headerOptions),
1013 headerOptions.size());
1018 result = OC_STACK_ERROR;
1024 OCStackApplicationResult deleteResourceCallback(void* ctx,
1025 OCDoHandle /*handle*/,
1026 OCClientResponse* clientResponse)
1028 ClientCallbackContext::DeleteContext* context =
1029 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
1030 HeaderOptions serverHeaderOptions;
1032 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1034 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
1036 return OC_STACK_DELETE_TRANSACTION;
1039 OCStackResult InProcClientWrapper::DeleteResource(
1040 const OCDevAddr& devAddr,
1041 const std::string& uri,
1042 const HeaderOptions& headerOptions,
1043 OCConnectivityType connectivityType,
1044 DeleteCallback& callback,
1045 QualityOfService /*QoS*/)
1049 return OC_STACK_INVALID_PARAM;
1051 OCStackResult result;
1052 ClientCallbackContext::DeleteContext* ctx =
1053 new ClientCallbackContext::DeleteContext(callback);
1054 OCCallbackData cbdata;
1055 cbdata.context = static_cast<void*>(ctx),
1056 cbdata.cb = deleteResourceCallback;
1057 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
1060 auto cLock = m_csdkLock.lock();
1064 OCHeaderOption options[MAX_HEADER_OPTIONS];
1066 std::lock_guard<std::recursive_mutex> lock(*cLock);
1068 result = OCDoResource(nullptr, OC_REST_DELETE,
1069 uri.c_str(), &devAddr,
1072 static_cast<OCQualityOfService>(m_cfg.QoS),
1074 assembleHeaderOptions(options, headerOptions),
1075 headerOptions.size());
1080 result = OC_STACK_ERROR;
1086 OCStackApplicationResult observeResourceCallback(void* ctx,
1087 OCDoHandle /*handle*/,
1088 OCClientResponse* clientResponse)
1090 ClientCallbackContext::ObserveContext* context =
1091 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1092 OCRepresentation attrs;
1093 HeaderOptions serverHeaderOptions;
1094 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1095 OCStackResult result = clientResponse->result;
1097 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1100 attrs = parseGetSetCallback(clientResponse);
1102 catch(OC::OCException& e)
1107 std::thread exec(context->callback, serverHeaderOptions, attrs,
1108 result, sequenceNumber);
1110 if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
1112 return OC_STACK_DELETE_TRANSACTION;
1115 return OC_STACK_KEEP_TRANSACTION;
1118 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1119 const OCDevAddr& devAddr,
1120 const std::string& uri,
1121 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1122 ObserveCallback& callback, QualityOfService QoS)
1126 return OC_STACK_INVALID_PARAM;
1128 OCStackResult result;
1130 ClientCallbackContext::ObserveContext* ctx =
1131 new ClientCallbackContext::ObserveContext(callback);
1132 OCCallbackData cbdata;
1133 cbdata.context = static_cast<void*>(ctx),
1134 cbdata.cb = observeResourceCallback;
1135 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1139 if (observeType == ObserveType::Observe)
1141 method = OC_REST_OBSERVE;
1143 else if (observeType == ObserveType::ObserveAll)
1145 method = OC_REST_OBSERVE_ALL;
1149 method = OC_REST_OBSERVE_ALL;
1152 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1154 auto cLock = m_csdkLock.lock();
1158 std::lock_guard<std::recursive_mutex> lock(*cLock);
1159 OCHeaderOption options[MAX_HEADER_OPTIONS];
1161 result = OCDoResource(handle, method,
1162 url.c_str(), &devAddr,
1165 static_cast<OCQualityOfService>(QoS),
1167 assembleHeaderOptions(options, headerOptions),
1168 headerOptions.size());
1173 return OC_STACK_ERROR;
1179 OCStackResult InProcClientWrapper::CancelObserveResource(
1181 const std::string& /*host*/,
1182 const std::string& /*uri*/,
1183 const HeaderOptions& headerOptions,
1184 QualityOfService QoS)
1186 OCStackResult result;
1187 auto cLock = m_csdkLock.lock();
1191 std::lock_guard<std::recursive_mutex> lock(*cLock);
1192 OCHeaderOption options[MAX_HEADER_OPTIONS];
1194 result = OCCancel(handle,
1195 static_cast<OCQualityOfService>(QoS),
1196 assembleHeaderOptions(options, headerOptions),
1197 headerOptions.size());
1201 result = OC_STACK_ERROR;
1207 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1208 OCDoHandle /*handle*/,
1209 OCClientResponse* clientResponse)
1211 ClientCallbackContext::SubscribePresenceContext* context =
1212 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1215 * This a hack while we rethink presence subscription.
1217 std::string url = clientResponse->devAddr.addr;
1219 std::thread exec(context->callback, clientResponse->result,
1220 clientResponse->sequenceNumber, url);
1224 return OC_STACK_KEEP_TRANSACTION;
1227 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1228 const std::string& host, const std::string& resourceType,
1229 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1231 if (!presenceHandler)
1233 return OC_STACK_INVALID_PARAM;
1236 ClientCallbackContext::SubscribePresenceContext* ctx =
1237 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1238 OCCallbackData cbdata;
1239 cbdata.context = static_cast<void*>(ctx),
1240 cbdata.cb = subscribePresenceCallback;
1241 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1244 auto cLock = m_csdkLock.lock();
1246 std::ostringstream os;
1247 os << host << OC_RSRVD_PRESENCE_URI;
1249 if (!resourceType.empty())
1251 os << "?rt=" << resourceType;
1257 return OC_STACK_ERROR;
1260 return OCDoResource(handle, OC_REST_PRESENCE,
1261 os.str().c_str(), nullptr,
1262 nullptr, connectivityType,
1263 OC_LOW_QOS, &cbdata, NULL, 0);
1266 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1268 OCStackResult result;
1269 auto cLock = m_csdkLock.lock();
1273 std::lock_guard<std::recursive_mutex> lock(*cLock);
1274 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1278 result = OC_STACK_ERROR;
1285 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1286 const std::string& host,
1287 const std::vector<std::string>& di,
1288 OCConnectivityType connectivityType,
1289 ObserveCallback& callback)
1293 return OC_STACK_INVALID_PARAM;
1295 OCStackResult result;
1297 ClientCallbackContext::ObserveContext* ctx =
1298 new ClientCallbackContext::ObserveContext(callback);
1299 OCCallbackData cbdata;
1300 cbdata.context = static_cast<void*>(ctx),
1301 cbdata.cb = observeResourceCallback;
1302 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1304 auto cLock = m_csdkLock.lock();
1308 std::lock_guard<std::recursive_mutex> lock(*cLock);
1310 std::ostringstream os;
1311 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1312 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1313 std::string url = assembleSetResourceUri(os.str(), queryParams);
1315 result = OCDoResource(handle, OC_REST_OBSERVE,
1316 url.c_str(), nullptr,
1317 nullptr, connectivityType,
1318 OC_LOW_QOS, &cbdata,
1324 result = OC_STACK_ERROR;
1331 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1337 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1338 const HeaderOptions& headerOptions)
1342 if ( headerOptions.size() == 0)
1347 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1349 options[i] = OCHeaderOption();
1350 options[i].protocolID = OC_COAP_ID;
1351 options[i].optionID = it->getOptionID();
1352 options[i].optionLength = it->getOptionData().length() + 1;
1353 strcpy((char*)options[i].optionData, (it->getOptionData().c_str()));
1360 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1367 OCDPDev_t* result = new OCDPDev_t(*dev);
1368 result->prm = new OCPrm_t[dev->prmLen];
1369 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1370 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1373 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1377 dpList.push_back(cloneDevice(list));
1382 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1383 GetDirectPairedCallback& callback)
1385 if (!callback || 0 == waittime)
1387 return OC_STACK_INVALID_PARAM;
1390 OCStackResult result = OC_STACK_ERROR;
1391 const OCDPDev_t *list = nullptr;
1392 PairedDevices dpDeviceList;
1394 auto cLock = m_csdkLock.lock();
1398 std::lock_guard<std::recursive_mutex> lock(*cLock);
1400 list = OCDiscoverDirectPairingDevices(waittime);
1403 result = OC_STACK_NO_RESOURCE;
1404 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1408 convert(list, dpDeviceList);
1409 std::thread exec(callback, dpDeviceList);
1411 result = OC_STACK_OK;
1416 result = OC_STACK_ERROR;
1422 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1426 return OC_STACK_INVALID_PARAM;
1429 OCStackResult result = OC_STACK_ERROR;
1430 const OCDPDev_t *list = nullptr;
1431 PairedDevices dpDeviceList;
1433 auto cLock = m_csdkLock.lock();
1437 std::lock_guard<std::recursive_mutex> lock(*cLock);
1439 list = OCGetDirectPairedDevices();
1442 result = OC_STACK_NO_RESOURCE;
1443 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1447 convert(list, dpDeviceList);
1448 std::thread exec(callback, dpDeviceList);
1450 result = OC_STACK_OK;
1455 result = OC_STACK_ERROR;
1461 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1462 OCStackResult result)
1465 ClientCallbackContext::DirectPairingContext* context =
1466 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1468 std::thread exec(context->callback, cloneDevice(peer), result);
1472 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1473 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1475 if (!peer || !callback)
1477 oclog() << "Invalid parameters" << std::flush;
1478 return OC_STACK_INVALID_PARAM;
1481 OCStackResult result = OC_STACK_ERROR;
1482 ClientCallbackContext::DirectPairingContext* context =
1483 new ClientCallbackContext::DirectPairingContext(callback);
1485 auto cLock = m_csdkLock.lock();
1488 std::lock_guard<std::recursive_mutex> lock(*cLock);
1489 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1490 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1495 result = OC_STACK_ERROR;