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>
30 #include "oickeepalive.h"
33 #define TAG "OIC_CLIENT_WRAPPER"
39 InProcClientWrapper::InProcClientWrapper(
40 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
41 : m_threadRun(false), m_csdkLock(csdkLock),
44 // if the config type is server, we ought to never get called. If the config type
45 // is both, we count on the server to run the thread and do the initialize
49 InProcClientWrapper::~InProcClientWrapper()
55 catch (InitializeException &e)
57 oclog() << "Exception in stop"<< e.what() << std::flush;
61 OCStackResult InProcClientWrapper::start()
63 OIC_LOG_V(INFO, TAG, "start ocplatform for client : %d", m_cfg.transportType);
65 if (m_cfg.mode == ModeType::Client)
67 OCTransportFlags serverFlags =
68 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
69 OCTransportFlags clientFlags =
70 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
71 OCStackResult result = OCInit2(OC_CLIENT, serverFlags, clientFlags,
74 if (OC_STACK_OK != result)
76 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
79 if (false == m_threadRun)
82 m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
88 OCStackResult InProcClientWrapper::stop()
90 OIC_LOG(INFO, TAG, "stop ocplatform");
92 if (m_threadRun && m_listeningThread.joinable())
95 m_listeningThread.join();
98 // only stop if we are the ones who actually called 'start'. We are counting
99 // on the server to do the stop.
100 if (m_cfg.mode == ModeType::Client)
102 OCStackResult result = OCStop();
104 if (OC_STACK_OK != result)
106 throw InitializeException(OC::InitException::STACK_TERMINATE_ERROR, result);
112 void InProcClientWrapper::listeningFunc()
116 OCStackResult result;
117 auto cLock = m_csdkLock.lock();
120 std::lock_guard<std::recursive_mutex> lock(*cLock);
121 result = OCProcess();
125 result = OC_STACK_ERROR;
128 if (result != OC_STACK_OK)
130 // TODO: do something with result if failed?
133 // To minimize CPU utilization we may wish to do this with sleep
134 std::this_thread::sleep_for(std::chrono::milliseconds(10));
138 OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
140 if (clientResponse->payload == nullptr ||
142 clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
146 return OCRepresentation();
150 oc.setPayload(clientResponse->payload);
152 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
153 if (it == oc.representations().end())
155 return OCRepresentation();
158 // first one is considered the root, everything else is considered a child of this one.
159 OCRepresentation root = *it;
160 root.setDevAddr(clientResponse->devAddr);
161 root.setUri(clientResponse->resourceUri);
164 std::for_each(it, oc.representations().end(),
165 [&root](const OCRepresentation& repItr)
166 {root.addChild(repItr);});
170 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
171 OCClientResponse* clientResponse)
173 if (!ctx || !clientResponse)
175 return OC_STACK_KEEP_TRANSACTION;
178 ClientCallbackContext::ListenContext* context =
179 static_cast<ClientCallbackContext::ListenContext*>(ctx);
181 if (clientResponse->result != OC_STACK_OK)
183 oclog() << "listenCallback(): failed to create resource. clientResponse: "
184 << clientResponse->result
187 return OC_STACK_KEEP_TRANSACTION;
190 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
192 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
194 return OC_STACK_KEEP_TRANSACTION;
197 auto clientWrapper = context->clientWrapper.lock();
201 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
203 return OC_STACK_KEEP_TRANSACTION;
208 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
209 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
210 // loop to ensure valid construction of all resources
212 for(auto resource : container.Resources())
214 std::thread exec(context->callback, resource);
218 catch (std::exception &e)
220 oclog() << "Exception in listCallback, ignoring response: "
221 << e.what() << std::flush;
225 return OC_STACK_KEEP_TRANSACTION;
228 OCStackApplicationResult listenErrorCallback(void* ctx, OCDoHandle /*handle*/,
229 OCClientResponse* clientResponse)
231 if (!ctx || !clientResponse)
233 return OC_STACK_KEEP_TRANSACTION;
236 ClientCallbackContext::ListenErrorContext* context =
237 static_cast<ClientCallbackContext::ListenErrorContext*>(ctx);
239 OCStackResult result = clientResponse->result;
240 if (result == OC_STACK_OK)
242 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
244 OIC_LOG_V(DEBUG, TAG, "%s: clientResponse payload was null or the wrong type",
246 return OC_STACK_KEEP_TRANSACTION;
249 auto clientWrapper = context->clientWrapper.lock();
253 OIC_LOG_V(DEBUG, TAG, "%s: failed to get a shared_ptr to the client wrapper",
255 return OC_STACK_KEEP_TRANSACTION;
258 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
259 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
260 // loop to ensure valid construction of all resources
261 for (auto resource : container.Resources())
263 std::thread exec(context->callback, resource);
266 return OC_STACK_KEEP_TRANSACTION;
269 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
270 std::string resourceURI;
271 if(NULL != clientResponse->resourceUri)
273 resourceURI = clientResponse->resourceUri;
276 std::thread exec(context->errorCallback, resourceURI, result);
278 return OC_STACK_KEEP_TRANSACTION;
281 OCStackResult InProcClientWrapper::ListenForResource(
282 const std::string& serviceUrl,
283 const std::string& resourceType,
284 OCConnectivityType connectivityType,
285 FindCallback& callback, QualityOfService QoS)
289 return OC_STACK_INVALID_PARAM;
292 OCStackResult result;
293 ostringstream resourceUri;
294 resourceUri << serviceUrl << resourceType;
296 ClientCallbackContext::ListenContext* context =
297 new ClientCallbackContext::ListenContext(callback, shared_from_this());
298 OCCallbackData cbdata;
299 cbdata.context = static_cast<void*>(context),
300 cbdata.cb = listenCallback;
301 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenContext*)c;};
303 auto cLock = m_csdkLock.lock();
306 std::lock_guard<std::recursive_mutex> lock(*cLock);
307 result = OCDoResource(nullptr, OC_REST_DISCOVER,
308 resourceUri.str().c_str(),
309 nullptr, nullptr, connectivityType,
310 static_cast<OCQualityOfService>(QoS),
317 result = OC_STACK_ERROR;
322 OCStackResult InProcClientWrapper::ListenErrorForResource(
323 const std::string& serviceUrl,
324 const std::string& resourceType,
325 OCConnectivityType connectivityType,
326 FindCallback& callback, FindErrorCallback& errorCallback,
327 QualityOfService QoS)
331 return OC_STACK_INVALID_PARAM;
334 ostringstream resourceUri;
335 resourceUri << serviceUrl << resourceType;
337 ClientCallbackContext::ListenErrorContext* context =
338 new ClientCallbackContext::ListenErrorContext(callback, errorCallback,
342 return OC_STACK_ERROR;
345 OCCallbackData cbdata(
346 static_cast<void*>(context),
348 [](void* c){delete static_cast<ClientCallbackContext::ListenErrorContext*>(c);}
351 OCStackResult result;
352 auto cLock = m_csdkLock.lock();
355 std::lock_guard<std::recursive_mutex> lock(*cLock);
356 result = OCDoResource(nullptr, OC_REST_DISCOVER,
357 resourceUri.str().c_str(),
358 nullptr, nullptr, connectivityType,
359 static_cast<OCQualityOfService>(QoS),
366 result = OC_STACK_ERROR;
371 OCStackApplicationResult listenResListCallback(void* ctx, OCDoHandle /*handle*/,
372 OCClientResponse* clientResponse)
374 if (!ctx || !clientResponse)
376 return OC_STACK_KEEP_TRANSACTION;
379 ClientCallbackContext::ListenResListContext* context =
380 static_cast<ClientCallbackContext::ListenResListContext*>(ctx);
382 if (clientResponse->result != OC_STACK_OK)
384 oclog() << "listenResListCallback(): failed to create resource. clientResponse: "
385 << clientResponse->result
388 return OC_STACK_KEEP_TRANSACTION;
391 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
393 oclog() << "listenResListCallback(): clientResponse payload was null or the wrong type"
395 return OC_STACK_KEEP_TRANSACTION;
398 auto clientWrapper = context->clientWrapper.lock();
402 oclog() << "listenResListCallback(): failed to get a shared_ptr to the client wrapper"
404 return OC_STACK_KEEP_TRANSACTION;
409 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
410 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
412 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
413 std::thread exec(context->callback, container.Resources());
416 catch (std::exception &e)
418 oclog() << "Exception in listenResListCallback(), ignoring response: "
419 << e.what() << std::flush;
422 return OC_STACK_KEEP_TRANSACTION;
425 OCStackResult InProcClientWrapper::ListenForResourceList(
426 const std::string& serviceUrl,
427 const std::string& resourceType,
428 OCConnectivityType connectivityType,
429 FindResListCallback& callback, QualityOfService QoS)
433 return OC_STACK_INVALID_PARAM;
436 OCStackResult result;
437 ostringstream resourceUri;
438 resourceUri << serviceUrl << resourceType;
440 ClientCallbackContext::ListenResListContext* context =
441 new ClientCallbackContext::ListenResListContext(callback, shared_from_this());
442 OCCallbackData cbdata;
443 cbdata.context = static_cast<void*>(context),
444 cbdata.cb = listenResListCallback;
445 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenResListContext*)c;};
447 auto cLock = m_csdkLock.lock();
450 std::lock_guard<std::recursive_mutex> lock(*cLock);
451 result = OCDoResource(nullptr, OC_REST_DISCOVER,
452 resourceUri.str().c_str(),
453 nullptr, nullptr, connectivityType,
454 static_cast<OCQualityOfService>(QoS),
461 result = OC_STACK_ERROR;
466 OCStackApplicationResult listenResListWithErrorCallback(void* ctx, OCDoHandle /*handle*/,
467 OCClientResponse* clientResponse)
469 if (!ctx || !clientResponse)
471 return OC_STACK_KEEP_TRANSACTION;
474 ClientCallbackContext::ListenResListWithErrorContext* context =
475 static_cast<ClientCallbackContext::ListenResListWithErrorContext*>(ctx);
477 OCStackResult result = clientResponse->result;
478 if (result != OC_STACK_OK)
480 oclog() << "listenResListWithErrorCallback(): failed to create resource. clientResponse: "
481 << result << std::flush;
483 //send the error callback
485 if(NULL != clientResponse->resourceUri)
487 uri = clientResponse->resourceUri;
489 std::thread exec(context->errorCallback, uri, result);
491 return OC_STACK_KEEP_TRANSACTION;
494 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
496 oclog() << "listenResListWithErrorCallback(): clientResponse payload was null or the wrong type"
498 return OC_STACK_KEEP_TRANSACTION;
501 auto clientWrapper = context->clientWrapper.lock();
505 oclog() << "listenResListWithErrorCallback(): failed to get a shared_ptr to the client wrapper"
507 return OC_STACK_KEEP_TRANSACTION;
512 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
513 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
515 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
516 std::thread exec(context->callback, container.Resources());
519 catch (std::exception &e)
521 oclog() << "Exception in listenResListWithErrorCallback(), ignoring response: "
522 << e.what() << std::flush;
525 return OC_STACK_KEEP_TRANSACTION;
528 OCStackResult InProcClientWrapper::ListenForResourceListWithError(
529 const std::string& serviceUrl,
530 const std::string& resourceType,
531 OCConnectivityType connectivityType,
532 FindResListCallback& callback,
533 FindErrorCallback& errorCallback, QualityOfService QoS)
537 return OC_STACK_INVALID_PARAM;
540 OCStackResult result;
541 ostringstream resourceUri;
542 resourceUri << serviceUrl << resourceType;
544 ClientCallbackContext::ListenResListWithErrorContext* context =
545 new ClientCallbackContext::ListenResListWithErrorContext(callback, errorCallback,
549 return OC_STACK_ERROR;
552 OCCallbackData cbdata;
553 cbdata.context = static_cast<void*>(context),
554 cbdata.cb = listenResListWithErrorCallback;
555 cbdata.cd = [](void* c){delete (ClientCallbackContext::ListenResListWithErrorContext*)c;};
557 auto cLock = m_csdkLock.lock();
560 std::lock_guard<std::recursive_mutex> lock(*cLock);
561 result = OCDoResource(nullptr, OC_REST_DISCOVER,
562 resourceUri.str().c_str(),
563 nullptr, nullptr, connectivityType,
564 static_cast<OCQualityOfService>(QoS),
571 result = OC_STACK_ERROR;
577 OCStackApplicationResult listenMQCallback(void* ctx, OCDoHandle /*handle*/,
578 OCClientResponse* clientResponse)
580 ClientCallbackContext::MQTopicContext* context =
581 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
583 if (!clientResponse || !context)
585 return OC_STACK_DELETE_TRANSACTION;
588 std::string resourceURI;
589 if(NULL != clientResponse->resourceUri)
591 resourceURI = clientResponse->resourceUri;
594 if (clientResponse->result != OC_STACK_OK)
596 oclog() << "listenMQCallback(): failed to create resource. clientResponse: "
597 << clientResponse->result
600 std::thread exec(context->callback, clientResponse->result,
601 resourceURI, nullptr);
604 return OC_STACK_DELETE_TRANSACTION;
607 auto clientWrapper = context->clientWrapper.lock();
610 oclog() << "listenMQCallback(): failed to get a shared_ptr to the client wrapper"
612 return OC_STACK_DELETE_TRANSACTION;
617 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
618 (OCRepPayload *) clientResponse->payload);
620 // loop to ensure valid construction of all resources
621 for (auto resource : container.Resources())
623 std::thread exec(context->callback, clientResponse->result,
624 resourceURI, resource);
628 catch (std::exception &e)
630 oclog() << "Exception in listCallback, ignoring response: "
631 << e.what() << std::flush;
634 return OC_STACK_DELETE_TRANSACTION;
637 OCStackResult InProcClientWrapper::ListenForMQTopic(const OCDevAddr& devAddr,
638 const std::string& resourceUri,
639 const QueryParamsMap& queryParams,
640 const HeaderOptions& headerOptions,
641 MQTopicCallback& callback,
642 QualityOfService QoS)
644 oclog() << "ListenForMQTopic()" << std::flush;
648 return OC_STACK_INVALID_PARAM;
651 ClientCallbackContext::MQTopicContext* context =
652 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
653 OCCallbackData cbdata;
654 cbdata.context = static_cast<void*>(context),
655 cbdata.cb = listenMQCallback;
656 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
658 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
660 OCStackResult result = OC_STACK_ERROR;
661 auto cLock = m_csdkLock.lock();
664 std::lock_guard<std::recursive_mutex> lock(*cLock);
665 OCHeaderOption options[MAX_HEADER_OPTIONS];
666 result = OCDoResource(
667 nullptr, OC_REST_GET,
671 static_cast<OCQualityOfService>(QoS),
673 assembleHeaderOptions(options, headerOptions),
674 headerOptions.size());
685 OCStackApplicationResult listenDeviceCallback(void* ctx,
686 OCDoHandle /*handle*/,
687 OCClientResponse* clientResponse)
689 ClientCallbackContext::DeviceListenContext* context =
690 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
694 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
695 OCRepresentation rep = parseGetSetCallback(clientResponse);
696 std::thread exec(context->callback, rep);
699 catch(OC::OCException& e)
701 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
702 <<e.what() <<std::flush;
705 return OC_STACK_KEEP_TRANSACTION;
708 OCStackResult InProcClientWrapper::ListenForDevice(
709 const std::string& serviceUrl,
710 const std::string& deviceURI,
711 OCConnectivityType connectivityType,
712 FindDeviceCallback& callback,
713 QualityOfService QoS)
717 return OC_STACK_INVALID_PARAM;
719 OCStackResult result;
720 ostringstream deviceUri;
721 deviceUri << serviceUrl << deviceURI;
723 ClientCallbackContext::DeviceListenContext* context =
724 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
725 OCCallbackData cbdata;
727 cbdata.context = static_cast<void*>(context),
728 cbdata.cb = listenDeviceCallback;
729 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
731 auto cLock = m_csdkLock.lock();
734 std::lock_guard<std::recursive_mutex> lock(*cLock);
735 result = OCDoResource(nullptr, OC_REST_DISCOVER,
736 deviceUri.str().c_str(),
737 nullptr, nullptr, connectivityType,
738 static_cast<OCQualityOfService>(QoS),
745 result = OC_STACK_ERROR;
750 void parseServerHeaderOptions(OCClientResponse* clientResponse,
751 HeaderOptions& serverHeaderOptions)
755 // Parse header options from server
757 std::string optionData;
759 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
761 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
762 optionData = reinterpret_cast<const char*>
763 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
764 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
765 serverHeaderOptions.push_back(headerOption);
770 // clientResponse is invalid
771 // TODO check proper logging
772 std::cout << " Invalid response " << std::endl;
777 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
778 OCClientResponse* clientResponse)
780 ClientCallbackContext::MQTopicContext* context =
781 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
782 HeaderOptions serverHeaderOptions;
784 if (!clientResponse || !context)
786 return OC_STACK_DELETE_TRANSACTION;
789 std::string createdUri;
790 bool isLocationOption = false;
791 OCStackResult result = clientResponse->result;
792 if (OC_STACK_OK == result ||
793 OC_STACK_RESOURCE_CREATED == result)
795 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
797 for (auto headerOption : serverHeaderOptions)
799 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
802 createdUri += headerOption.getOptionData();
803 if (!isLocationOption)
805 isLocationOption = true;
811 if (!isLocationOption && NULL != clientResponse->resourceUri)
813 createdUri = std::string(clientResponse->resourceUri);
816 auto clientWrapper = context->clientWrapper.lock();
820 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
822 return OC_STACK_DELETE_TRANSACTION;
827 if (OC_STACK_OK == result ||
828 OC_STACK_RESOURCE_CREATED == result)
830 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
832 for (auto resource : container.Resources())
834 std::thread exec(context->callback, result,
842 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
843 std::thread exec(context->callback, result,
849 catch (std::exception &e)
851 oclog() << "Exception in createMQTopicCallback, ignoring response: "
852 << e.what() << std::flush;
854 return OC_STACK_DELETE_TRANSACTION;
857 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
858 const OCDevAddr& devAddr,
859 const std::string& uri,
860 const OCRepresentation& rep,
861 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
862 MQTopicCallback& callback, QualityOfService QoS)
866 return OC_STACK_INVALID_PARAM;
868 OCStackResult result;
869 ClientCallbackContext::MQTopicContext* ctx =
870 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
871 OCCallbackData cbdata;
872 cbdata.context = static_cast<void*>(ctx),
873 cbdata.cb = createMQTopicCallback;
874 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
876 std::string url = assembleSetResourceUri(uri, queryParams);
878 auto cLock = m_csdkLock.lock();
882 std::lock_guard<std::recursive_mutex> lock(*cLock);
883 OCHeaderOption options[MAX_HEADER_OPTIONS];
885 result = OCDoResource(nullptr, OC_REST_PUT,
886 url.c_str(), &devAddr,
887 assembleSetResourcePayload(rep),
889 static_cast<OCQualityOfService>(QoS),
891 assembleHeaderOptions(options, headerOptions),
892 headerOptions.size());
897 result = OC_STACK_ERROR;
903 OCStackApplicationResult getResourceCallback(void* ctx,
904 OCDoHandle /*handle*/,
905 OCClientResponse* clientResponse)
907 ClientCallbackContext::GetContext* context =
908 static_cast<ClientCallbackContext::GetContext*>(ctx);
909 OCRepresentation rep;
910 HeaderOptions serverHeaderOptions;
911 OCStackResult result = clientResponse->result;
913 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
916 rep = parseGetSetCallback(clientResponse);
918 catch(OC::OCException& e)
923 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
924 std::thread exec(context->callback, serverHeaderOptions, rep, result);
926 return OC_STACK_DELETE_TRANSACTION;
929 OCStackResult InProcClientWrapper::GetResourceRepresentation(
930 const OCDevAddr& devAddr,
931 const std::string& resourceUri,
932 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
933 OCConnectivityType connectivityType,
934 GetCallback& callback, QualityOfService QoS)
938 return OC_STACK_INVALID_PARAM;
940 OCStackResult result;
941 ClientCallbackContext::GetContext* ctx =
942 new ClientCallbackContext::GetContext(callback);
944 OCCallbackData cbdata;
945 cbdata.context = static_cast<void*>(ctx);
946 cbdata.cb = getResourceCallback;
947 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
949 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
951 auto cLock = m_csdkLock.lock();
955 std::lock_guard<std::recursive_mutex> lock(*cLock);
956 OCHeaderOption options[MAX_HEADER_OPTIONS];
958 result = OCDoResource(
959 nullptr, OC_REST_GET,
963 static_cast<OCQualityOfService>(QoS),
965 assembleHeaderOptions(options, headerOptions),
966 headerOptions.size());
971 result = OC_STACK_ERROR;
977 OCStackApplicationResult setResourceCallback(void* ctx,
978 OCDoHandle /*handle*/,
979 OCClientResponse* clientResponse)
981 ClientCallbackContext::SetContext* context =
982 static_cast<ClientCallbackContext::SetContext*>(ctx);
983 OCRepresentation attrs;
984 HeaderOptions serverHeaderOptions;
986 OCStackResult result = clientResponse->result;
988 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
991 attrs = parseGetSetCallback(clientResponse);
993 catch(OC::OCException& e)
998 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
999 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
1001 return OC_STACK_DELETE_TRANSACTION;
1004 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
1005 const QueryParamsMap& queryParams)
1009 if (uri.back() == '/')
1011 uri.resize(uri.size() - 1);
1015 ostringstream paramsList;
1016 if (queryParams.size() > 0)
1021 for (auto& param : queryParams)
1023 paramsList << param.first <<'='<<param.second<<';';
1026 std::string queryString = paramsList.str();
1028 if (queryString.empty())
1033 if (queryString.back() == ';')
1035 queryString.resize(queryString.size() - 1);
1038 std::string ret = uri + queryString;
1042 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
1043 const QueryParamsList& queryParams)
1047 if (uri.back() == '/')
1049 uri.resize(uri.size() - 1);
1053 ostringstream paramsList;
1054 if (queryParams.size() > 0)
1059 for (auto& param : queryParams)
1061 for (auto& paramList : param.second)
1063 paramsList << param.first << '=' << paramList << ';';
1067 std::string queryString = paramsList.str();
1069 if (queryString.empty())
1074 if (queryString.back() == ';')
1076 queryString.resize(queryString.size() - 1);
1079 std::string ret = uri + queryString;
1083 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
1085 MessageContainer ocInfo;
1086 ocInfo.addRepresentation(rep);
1087 for(const OCRepresentation& r : rep.getChildren())
1089 ocInfo.addRepresentation(r);
1092 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
1095 OCStackResult InProcClientWrapper::PostResourceRepresentation(
1096 const OCDevAddr& devAddr,
1097 const std::string& uri,
1098 const OCRepresentation& rep,
1099 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1100 OCConnectivityType connectivityType,
1101 PostCallback& callback, QualityOfService QoS)
1105 return OC_STACK_INVALID_PARAM;
1107 OCStackResult result;
1108 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
1109 OCCallbackData cbdata;
1110 cbdata.context = static_cast<void*>(ctx),
1111 cbdata.cb = setResourceCallback;
1112 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
1115 std::string url = assembleSetResourceUri(uri, queryParams);
1117 auto cLock = m_csdkLock.lock();
1121 std::lock_guard<std::recursive_mutex> lock(*cLock);
1122 OCHeaderOption options[MAX_HEADER_OPTIONS];
1124 result = OCDoResource(nullptr, OC_REST_POST,
1125 url.c_str(), &devAddr,
1126 assembleSetResourcePayload(rep),
1128 static_cast<OCQualityOfService>(QoS),
1130 assembleHeaderOptions(options, headerOptions),
1131 headerOptions.size());
1136 result = OC_STACK_ERROR;
1142 OCStackResult InProcClientWrapper::PutResourceRepresentation(
1143 const OCDevAddr& devAddr,
1144 const std::string& uri,
1145 const OCRepresentation& rep,
1146 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1147 PutCallback& callback, QualityOfService QoS)
1151 return OC_STACK_INVALID_PARAM;
1153 OCStackResult result;
1154 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
1155 OCCallbackData cbdata;
1156 cbdata.context = static_cast<void*>(ctx),
1157 cbdata.cb = setResourceCallback;
1158 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
1161 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1163 auto cLock = m_csdkLock.lock();
1167 std::lock_guard<std::recursive_mutex> lock(*cLock);
1169 OCHeaderOption options[MAX_HEADER_OPTIONS];
1171 result = OCDoResource(&handle, OC_REST_PUT,
1172 url.c_str(), &devAddr,
1173 assembleSetResourcePayload(rep),
1175 static_cast<OCQualityOfService>(QoS),
1177 assembleHeaderOptions(options, headerOptions),
1178 headerOptions.size());
1183 result = OC_STACK_ERROR;
1189 OCStackApplicationResult deleteResourceCallback(void* ctx,
1190 OCDoHandle /*handle*/,
1191 OCClientResponse* clientResponse)
1193 ClientCallbackContext::DeleteContext* context =
1194 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
1195 HeaderOptions serverHeaderOptions;
1197 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1199 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1200 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
1202 return OC_STACK_DELETE_TRANSACTION;
1205 OCStackResult InProcClientWrapper::DeleteResource(
1206 const OCDevAddr& devAddr,
1207 const std::string& uri,
1208 const HeaderOptions& headerOptions,
1209 OCConnectivityType connectivityType,
1210 DeleteCallback& callback,
1211 QualityOfService /*QoS*/)
1215 return OC_STACK_INVALID_PARAM;
1217 OCStackResult result;
1218 ClientCallbackContext::DeleteContext* ctx =
1219 new ClientCallbackContext::DeleteContext(callback);
1220 OCCallbackData cbdata;
1221 cbdata.context = static_cast<void*>(ctx),
1222 cbdata.cb = deleteResourceCallback;
1223 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
1226 auto cLock = m_csdkLock.lock();
1230 OCHeaderOption options[MAX_HEADER_OPTIONS];
1232 std::lock_guard<std::recursive_mutex> lock(*cLock);
1234 result = OCDoResource(nullptr, OC_REST_DELETE,
1235 uri.c_str(), &devAddr,
1238 static_cast<OCQualityOfService>(m_cfg.QoS),
1240 assembleHeaderOptions(options, headerOptions),
1241 headerOptions.size());
1246 result = OC_STACK_ERROR;
1252 OCStackApplicationResult observeResourceCallback(void* ctx,
1253 OCDoHandle /*handle*/,
1254 OCClientResponse* clientResponse)
1256 ClientCallbackContext::ObserveContext* context =
1257 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1258 OCRepresentation attrs;
1259 HeaderOptions serverHeaderOptions;
1260 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1261 OCStackResult result = clientResponse->result;
1263 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1266 attrs = parseGetSetCallback(clientResponse);
1268 catch(OC::OCException& e)
1273 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1274 std::thread exec(context->callback, serverHeaderOptions, attrs,
1275 result, sequenceNumber);
1277 if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
1279 return OC_STACK_DELETE_TRANSACTION;
1282 return OC_STACK_KEEP_TRANSACTION;
1285 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1286 const OCDevAddr& devAddr,
1287 const std::string& uri,
1288 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1289 ObserveCallback& callback, QualityOfService QoS)
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;};
1306 if (observeType == ObserveType::Observe)
1308 method = OC_REST_OBSERVE;
1310 else if (observeType == ObserveType::ObserveAll)
1312 method = OC_REST_OBSERVE_ALL;
1316 method = OC_REST_OBSERVE_ALL;
1319 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1321 auto cLock = m_csdkLock.lock();
1325 std::lock_guard<std::recursive_mutex> lock(*cLock);
1326 OCHeaderOption options[MAX_HEADER_OPTIONS];
1328 result = OCDoResource(handle, method,
1329 url.c_str(), &devAddr,
1332 static_cast<OCQualityOfService>(QoS),
1334 assembleHeaderOptions(options, headerOptions),
1335 headerOptions.size());
1340 return OC_STACK_ERROR;
1346 OCStackResult InProcClientWrapper::CancelObserveResource(
1348 const std::string& /*host*/,
1349 const std::string& /*uri*/,
1350 const HeaderOptions& headerOptions,
1351 QualityOfService QoS)
1353 OCStackResult result;
1354 auto cLock = m_csdkLock.lock();
1358 std::lock_guard<std::recursive_mutex> lock(*cLock);
1359 OCHeaderOption options[MAX_HEADER_OPTIONS];
1361 result = OCCancel(handle,
1362 static_cast<OCQualityOfService>(QoS),
1363 assembleHeaderOptions(options, headerOptions),
1364 headerOptions.size());
1368 result = OC_STACK_ERROR;
1374 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1375 OCDoHandle /*handle*/,
1376 OCClientResponse* clientResponse)
1378 ClientCallbackContext::SubscribePresenceContext* context =
1379 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1382 * This a hack while we rethink presence subscription.
1384 std::string url = clientResponse->devAddr.addr;
1386 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1387 std::thread exec(context->callback, clientResponse->result,
1388 clientResponse->sequenceNumber, url);
1392 return OC_STACK_KEEP_TRANSACTION;
1395 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1396 const std::string& host, const std::string& resourceType,
1397 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1399 if (!presenceHandler)
1401 return OC_STACK_INVALID_PARAM;
1404 ClientCallbackContext::SubscribePresenceContext* ctx =
1405 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1406 OCCallbackData cbdata;
1407 cbdata.context = static_cast<void*>(ctx),
1408 cbdata.cb = subscribePresenceCallback;
1409 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1412 auto cLock = m_csdkLock.lock();
1414 std::ostringstream os;
1415 os << host << OC_RSRVD_PRESENCE_URI;
1417 if (!resourceType.empty())
1419 os << "?rt=" << resourceType;
1425 return OC_STACK_ERROR;
1428 return OCDoResource(handle, OC_REST_PRESENCE,
1429 os.str().c_str(), nullptr,
1430 nullptr, connectivityType,
1431 OC_LOW_QOS, &cbdata, NULL, 0);
1434 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1436 OCStackResult result;
1437 auto cLock = m_csdkLock.lock();
1441 std::lock_guard<std::recursive_mutex> lock(*cLock);
1442 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1446 result = OC_STACK_ERROR;
1453 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1454 const std::string& host,
1455 const std::vector<std::string>& di,
1456 OCConnectivityType connectivityType,
1457 ObserveCallback& callback)
1461 return OC_STACK_INVALID_PARAM;
1463 OCStackResult result;
1465 ClientCallbackContext::ObserveContext* ctx =
1466 new ClientCallbackContext::ObserveContext(callback);
1467 OCCallbackData cbdata;
1468 cbdata.context = static_cast<void*>(ctx),
1469 cbdata.cb = observeResourceCallback;
1470 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1472 auto cLock = m_csdkLock.lock();
1476 std::lock_guard<std::recursive_mutex> lock(*cLock);
1478 std::ostringstream os;
1479 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1480 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1481 std::string url = assembleSetResourceUri(os.str(), queryParams);
1483 result = OCDoResource(handle, OC_REST_OBSERVE,
1484 url.c_str(), nullptr,
1485 nullptr, connectivityType,
1486 OC_LOW_QOS, &cbdata,
1492 result = OC_STACK_ERROR;
1499 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1505 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
1506 const HeaderOptions& headerOptions)
1510 if ( headerOptions.size() == 0)
1515 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1517 options[i] = OCHeaderOption();
1518 options[i].protocolID = OC_COAP_ID;
1519 options[i].optionID = it->getOptionID();
1520 options[i].optionLength = it->getOptionData().length() + 1;
1521 strncpy((char*)options[i].optionData, it->getOptionData().c_str(),
1522 sizeof(options[i].optionLength) -1 );
1523 options[i].optionData[sizeof(options[i].optionLength) - 1] = 0;
1530 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1537 OCDPDev_t* result = new OCDPDev_t(*dev);
1538 result->prm = new OCPrm_t[dev->prmLen];
1539 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1540 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1543 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1547 dpList.push_back(cloneDevice(list));
1552 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1553 GetDirectPairedCallback& callback)
1555 if (!callback || 0 == waittime)
1557 return OC_STACK_INVALID_PARAM;
1560 OCStackResult result = OC_STACK_ERROR;
1561 const OCDPDev_t *list = nullptr;
1562 PairedDevices dpDeviceList;
1564 auto cLock = m_csdkLock.lock();
1568 std::lock_guard<std::recursive_mutex> lock(*cLock);
1570 list = OCDiscoverDirectPairingDevices(waittime);
1573 result = OC_STACK_NO_RESOURCE;
1574 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1578 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1579 convert(list, dpDeviceList);
1580 std::thread exec(callback, dpDeviceList);
1582 result = OC_STACK_OK;
1587 result = OC_STACK_ERROR;
1593 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1597 return OC_STACK_INVALID_PARAM;
1600 OCStackResult result = OC_STACK_ERROR;
1601 const OCDPDev_t *list = nullptr;
1602 PairedDevices dpDeviceList;
1604 auto cLock = m_csdkLock.lock();
1608 std::lock_guard<std::recursive_mutex> lock(*cLock);
1610 list = OCGetDirectPairedDevices();
1613 result = OC_STACK_NO_RESOURCE;
1614 OIC_LOG_V(DEBUG, TAG, "%s: No device found for direct pairing", __func__);
1617 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1618 convert(list, dpDeviceList);
1619 std::thread exec(callback, dpDeviceList);
1621 result = OC_STACK_OK;
1626 result = OC_STACK_ERROR;
1632 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1633 OCStackResult result)
1636 ClientCallbackContext::DirectPairingContext* context =
1637 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1639 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1640 std::thread exec(context->callback, cloneDevice(peer), result);
1644 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1645 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1647 if (!peer || !callback)
1649 oclog() << "Invalid parameters" << std::flush;
1650 return OC_STACK_INVALID_PARAM;
1653 OCStackResult result = OC_STACK_ERROR;
1654 ClientCallbackContext::DirectPairingContext* context =
1655 new ClientCallbackContext::DirectPairingContext(callback);
1657 auto cLock = m_csdkLock.lock();
1660 std::lock_guard<std::recursive_mutex> lock(*cLock);
1661 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1662 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1667 result = OC_STACK_ERROR;
1672 OCStackApplicationResult KeepAliveRespCallback(void* ctx,
1673 OCDoHandle /*handle*/,
1674 OCClientResponse* clientResponse)
1676 ClientCallbackContext::KeepAliveContext* context =
1677 static_cast<ClientCallbackContext::KeepAliveContext*>(ctx);
1678 OCRepresentation attrs;
1679 OCStackResult result = clientResponse->result;
1683 attrs = parseGetSetCallback(clientResponse);
1685 catch(OC::OCException& e)
1690 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1691 std::thread exec(context->callback, result, attrs);
1693 return OC_STACK_DELETE_TRANSACTION;
1696 OCStackResult InProcClientWrapper::findKeepAliveResource(std::string host,
1697 KeepAliveCallback resultCallback)
1699 if (host.empty() || !resultCallback)
1701 oclog() << "Invalid parameters" << std::flush;
1702 return OC_STACK_INVALID_PARAM;
1705 OCStackResult result = OC_STACK_ERROR;
1707 ClientCallbackContext::KeepAliveContext* ctx =
1708 new ClientCallbackContext::KeepAliveContext(resultCallback);
1709 OCCallbackData cbdata;
1710 cbdata.context = static_cast<void*>(ctx),
1711 cbdata.cb = KeepAliveRespCallback;
1712 cbdata.cd = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
1714 auto cLock = m_csdkLock.lock();
1718 std::lock_guard<std::recursive_mutex> lock(*cLock);
1719 result = OCFindKeepAliveResource(nullptr, host.c_str(), &cbdata);
1724 result = OC_STACK_ERROR;
1729 OCStackResult InProcClientWrapper::sendKeepAliveRequest(std::string host,
1730 const OCRepresentation& rep,
1731 KeepAliveCallback resultCallback)
1733 if (!resultCallback)
1735 oclog() << "Invalid parameters" << std::flush;
1736 return OC_STACK_INVALID_PARAM;
1739 OCStackResult result = OC_STACK_ERROR;
1741 ClientCallbackContext::KeepAliveContext* ctx = new ClientCallbackContext::KeepAliveContext(resultCallback);
1742 OCCallbackData cbdata;
1743 cbdata.context = static_cast<void*>(ctx),
1744 cbdata.cb = KeepAliveRespCallback;
1745 cbdata.cd = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
1747 auto cLock = m_csdkLock.lock();
1751 std::lock_guard<std::recursive_mutex> lock(*cLock);
1752 OCRepPayload *payload = rep.getPayload();
1753 result = OCSendKeepAliveRequest (nullptr, host.c_str(), (OCPayload*)payload, &cbdata);
1754 if (result != OC_STACK_OK)
1756 OCRepPayloadDestroy(payload);
1762 result = OC_STACK_ERROR;