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 if (headerOptions.size() > MAX_HEADER_OPTIONS)
653 oclog() << "ListenForMQTopic: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
654 return OC_STACK_INVALID_PARAM;
657 ClientCallbackContext::MQTopicContext* context =
658 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
659 OCCallbackData cbdata;
660 cbdata.context = static_cast<void*>(context),
661 cbdata.cb = listenMQCallback;
662 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
664 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
666 OCStackResult result = OC_STACK_ERROR;
667 auto cLock = m_csdkLock.lock();
670 std::lock_guard<std::recursive_mutex> lock(*cLock);
671 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
672 result = OCDoResource(
673 nullptr, OC_REST_GET,
677 static_cast<OCQualityOfService>(QoS),
680 headerOptions.size());
692 OCStackApplicationResult listenDeviceCallback(void* ctx,
693 OCDoHandle /*handle*/,
694 OCClientResponse* clientResponse)
696 ClientCallbackContext::DeviceListenContext* context =
697 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
701 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
702 OCRepresentation rep = parseGetSetCallback(clientResponse);
703 std::thread exec(context->callback, rep);
706 catch(OC::OCException& e)
708 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
709 <<e.what() <<std::flush;
712 return OC_STACK_KEEP_TRANSACTION;
715 OCStackResult InProcClientWrapper::ListenForDevice(
716 const std::string& serviceUrl,
717 const std::string& deviceURI,
718 OCConnectivityType connectivityType,
719 FindDeviceCallback& callback,
720 QualityOfService QoS)
724 return OC_STACK_INVALID_PARAM;
726 OCStackResult result;
727 ostringstream deviceUri;
728 deviceUri << serviceUrl << deviceURI;
730 ClientCallbackContext::DeviceListenContext* context =
731 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
732 OCCallbackData cbdata;
734 cbdata.context = static_cast<void*>(context),
735 cbdata.cb = listenDeviceCallback;
736 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeviceListenContext*)c;};
738 auto cLock = m_csdkLock.lock();
741 std::lock_guard<std::recursive_mutex> lock(*cLock);
742 result = OCDoResource(nullptr, OC_REST_DISCOVER,
743 deviceUri.str().c_str(),
744 nullptr, nullptr, connectivityType,
745 static_cast<OCQualityOfService>(QoS),
752 result = OC_STACK_ERROR;
757 void parseServerHeaderOptions(OCClientResponse* clientResponse,
758 HeaderOptions& serverHeaderOptions)
762 // Parse header options from server
764 std::string optionData;
766 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
768 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
769 optionData = reinterpret_cast<const char*>
770 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
771 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
772 serverHeaderOptions.push_back(headerOption);
777 // clientResponse is invalid
778 // TODO check proper logging
779 std::cout << " Invalid response " << std::endl;
784 OCStackApplicationResult createMQTopicCallback(void* ctx, OCDoHandle /*handle*/,
785 OCClientResponse* clientResponse)
787 ClientCallbackContext::MQTopicContext* context =
788 static_cast<ClientCallbackContext::MQTopicContext*>(ctx);
789 HeaderOptions serverHeaderOptions;
791 if (!clientResponse || !context)
793 return OC_STACK_DELETE_TRANSACTION;
796 std::string createdUri;
797 bool isLocationOption = false;
798 OCStackResult result = clientResponse->result;
799 if (OC_STACK_OK == result ||
800 OC_STACK_RESOURCE_CREATED == result)
802 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
804 for (auto headerOption : serverHeaderOptions)
806 if (HeaderOption::LOCATION_PATH_OPTION_ID == headerOption.getOptionID())
809 createdUri += headerOption.getOptionData();
810 if (!isLocationOption)
812 isLocationOption = true;
818 if (!isLocationOption && NULL != clientResponse->resourceUri)
820 createdUri = std::string(clientResponse->resourceUri);
823 auto clientWrapper = context->clientWrapper.lock();
827 oclog() << "createMQTopicCallback(): failed to get a shared_ptr to the client wrapper"
829 return OC_STACK_DELETE_TRANSACTION;
834 if (OC_STACK_OK == result ||
835 OC_STACK_RESOURCE_CREATED == result)
837 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
839 for (auto resource : container.Resources())
841 std::thread exec(context->callback, result,
849 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
850 std::thread exec(context->callback, result,
856 catch (std::exception &e)
858 oclog() << "Exception in createMQTopicCallback, ignoring response: "
859 << e.what() << std::flush;
861 return OC_STACK_DELETE_TRANSACTION;
864 OCStackResult InProcClientWrapper::PutMQTopicRepresentation(
865 const OCDevAddr& devAddr,
866 const std::string& uri,
867 const OCRepresentation& rep,
868 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
869 MQTopicCallback& callback, QualityOfService QoS)
873 return OC_STACK_INVALID_PARAM;
876 if (headerOptions.size() > MAX_HEADER_OPTIONS)
878 oclog() << "PutMQTopicRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
879 return OC_STACK_INVALID_PARAM;
882 OCStackResult result;
883 ClientCallbackContext::MQTopicContext* ctx =
884 new ClientCallbackContext::MQTopicContext(callback, shared_from_this());
885 OCCallbackData cbdata;
886 cbdata.context = static_cast<void*>(ctx),
887 cbdata.cb = createMQTopicCallback;
888 cbdata.cd = [](void* c){delete (ClientCallbackContext::MQTopicContext*)c;};
890 std::string url = assembleSetResourceUri(uri, queryParams);
892 auto cLock = m_csdkLock.lock();
896 std::lock_guard<std::recursive_mutex> lock(*cLock);
897 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
899 result = OCDoResource(nullptr, OC_REST_PUT,
900 url.c_str(), &devAddr,
901 assembleSetResourcePayload(rep),
903 static_cast<OCQualityOfService>(QoS),
906 headerOptions.size());
912 result = OC_STACK_ERROR;
918 OCStackApplicationResult getResourceCallback(void* ctx,
919 OCDoHandle /*handle*/,
920 OCClientResponse* clientResponse)
922 ClientCallbackContext::GetContext* context =
923 static_cast<ClientCallbackContext::GetContext*>(ctx);
924 OCRepresentation rep;
925 HeaderOptions serverHeaderOptions;
926 OCStackResult result = clientResponse->result;
928 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
931 rep = parseGetSetCallback(clientResponse);
933 catch(OC::OCException& e)
938 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
939 std::thread exec(context->callback, serverHeaderOptions, rep, result);
941 return OC_STACK_DELETE_TRANSACTION;
944 OCStackResult InProcClientWrapper::GetResourceRepresentation(
945 const OCDevAddr& devAddr,
946 const std::string& resourceUri,
947 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
948 OCConnectivityType connectivityType,
949 GetCallback& callback, QualityOfService QoS)
953 return OC_STACK_INVALID_PARAM;
956 if (headerOptions.size() > MAX_HEADER_OPTIONS)
958 oclog() << "GetResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
959 return OC_STACK_INVALID_PARAM;
962 OCStackResult result;
963 ClientCallbackContext::GetContext* ctx =
964 new ClientCallbackContext::GetContext(callback);
966 OCCallbackData cbdata;
967 cbdata.context = static_cast<void*>(ctx);
968 cbdata.cb = getResourceCallback;
969 cbdata.cd = [](void* c){delete (ClientCallbackContext::GetContext*)c;};
971 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
973 auto cLock = m_csdkLock.lock();
977 std::lock_guard<std::recursive_mutex> lock(*cLock);
978 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
980 result = OCDoResource(
981 nullptr, OC_REST_GET,
985 static_cast<OCQualityOfService>(QoS),
988 headerOptions.size());
994 result = OC_STACK_ERROR;
1000 OCStackApplicationResult setResourceCallback(void* ctx,
1001 OCDoHandle /*handle*/,
1002 OCClientResponse* clientResponse)
1004 ClientCallbackContext::SetContext* context =
1005 static_cast<ClientCallbackContext::SetContext*>(ctx);
1006 OCRepresentation attrs;
1007 HeaderOptions serverHeaderOptions;
1009 OCStackResult result = clientResponse->result;
1011 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1014 attrs = parseGetSetCallback(clientResponse);
1016 catch(OC::OCException& e)
1021 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1022 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
1024 return OC_STACK_DELETE_TRANSACTION;
1027 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
1028 const QueryParamsMap& queryParams)
1032 if (uri.back() == '/')
1034 uri.resize(uri.size() - 1);
1038 ostringstream paramsList;
1039 if (queryParams.size() > 0)
1044 for (auto& param : queryParams)
1046 paramsList << param.first <<'='<<param.second<<';';
1049 std::string queryString = paramsList.str();
1051 if (queryString.empty())
1056 if (queryString.back() == ';')
1058 queryString.resize(queryString.size() - 1);
1061 std::string ret = uri + queryString;
1065 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
1066 const QueryParamsList& queryParams)
1070 if (uri.back() == '/')
1072 uri.resize(uri.size() - 1);
1076 ostringstream paramsList;
1077 if (queryParams.size() > 0)
1082 for (auto& param : queryParams)
1084 for (auto& paramList : param.second)
1086 paramsList << param.first << '=' << paramList << ';';
1090 std::string queryString = paramsList.str();
1092 if (queryString.empty())
1097 if (queryString.back() == ';')
1099 queryString.resize(queryString.size() - 1);
1102 std::string ret = uri + queryString;
1106 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
1108 MessageContainer ocInfo;
1109 ocInfo.addRepresentation(rep);
1110 for(const OCRepresentation& r : rep.getChildren())
1112 ocInfo.addRepresentation(r);
1115 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
1118 OCStackResult InProcClientWrapper::PostResourceRepresentation(
1119 const OCDevAddr& devAddr,
1120 const std::string& uri,
1121 const OCRepresentation& rep,
1122 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1123 OCConnectivityType connectivityType,
1124 PostCallback& callback, QualityOfService QoS)
1128 return OC_STACK_INVALID_PARAM;
1131 if (headerOptions.size() > MAX_HEADER_OPTIONS)
1133 oclog() << "PostResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
1134 return OC_STACK_INVALID_PARAM;
1137 OCStackResult result;
1138 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
1139 OCCallbackData cbdata;
1140 cbdata.context = static_cast<void*>(ctx),
1141 cbdata.cb = setResourceCallback;
1142 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
1145 std::string url = assembleSetResourceUri(uri, queryParams);
1147 auto cLock = m_csdkLock.lock();
1151 std::lock_guard<std::recursive_mutex> lock(*cLock);
1152 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
1154 result = OCDoResource(nullptr, OC_REST_POST,
1155 url.c_str(), &devAddr,
1156 assembleSetResourcePayload(rep),
1158 static_cast<OCQualityOfService>(QoS),
1161 headerOptions.size());
1167 result = OC_STACK_ERROR;
1173 OCStackResult InProcClientWrapper::PutResourceRepresentation(
1174 const OCDevAddr& devAddr,
1175 const std::string& uri,
1176 const OCRepresentation& rep,
1177 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1178 PutCallback& callback, QualityOfService QoS)
1182 return OC_STACK_INVALID_PARAM;
1185 if (headerOptions.size() > MAX_HEADER_OPTIONS)
1187 oclog() << "PutResourceRepresentation: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
1188 return OC_STACK_INVALID_PARAM;
1191 OCStackResult result;
1192 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
1193 OCCallbackData cbdata;
1194 cbdata.context = static_cast<void*>(ctx),
1195 cbdata.cb = setResourceCallback;
1196 cbdata.cd = [](void* c){delete (ClientCallbackContext::SetContext*)c;};
1199 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1201 auto cLock = m_csdkLock.lock();
1205 std::lock_guard<std::recursive_mutex> lock(*cLock);
1207 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
1209 result = OCDoResource(&handle, OC_REST_PUT,
1210 url.c_str(), &devAddr,
1211 assembleSetResourcePayload(rep),
1213 static_cast<OCQualityOfService>(QoS),
1216 headerOptions.size());
1222 result = OC_STACK_ERROR;
1228 OCStackApplicationResult deleteResourceCallback(void* ctx,
1229 OCDoHandle /*handle*/,
1230 OCClientResponse* clientResponse)
1232 ClientCallbackContext::DeleteContext* context =
1233 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
1234 HeaderOptions serverHeaderOptions;
1236 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1238 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1239 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
1241 return OC_STACK_DELETE_TRANSACTION;
1244 OCStackResult InProcClientWrapper::DeleteResource(
1245 const OCDevAddr& devAddr,
1246 const std::string& uri,
1247 const HeaderOptions& headerOptions,
1248 OCConnectivityType connectivityType,
1249 DeleteCallback& callback,
1250 QualityOfService /*QoS*/)
1254 return OC_STACK_INVALID_PARAM;
1257 if (headerOptions.size() > MAX_HEADER_OPTIONS)
1259 oclog() << "DeleteResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
1260 return OC_STACK_INVALID_PARAM;
1263 OCStackResult result;
1264 ClientCallbackContext::DeleteContext* ctx =
1265 new ClientCallbackContext::DeleteContext(callback);
1266 OCCallbackData cbdata;
1267 cbdata.context = static_cast<void*>(ctx),
1268 cbdata.cb = deleteResourceCallback;
1269 cbdata.cd = [](void* c){delete (ClientCallbackContext::DeleteContext*)c;};
1272 auto cLock = m_csdkLock.lock();
1276 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
1278 std::lock_guard<std::recursive_mutex> lock(*cLock);
1280 result = OCDoResource(nullptr, OC_REST_DELETE,
1281 uri.c_str(), &devAddr,
1284 static_cast<OCQualityOfService>(m_cfg.QoS),
1287 headerOptions.size());
1293 result = OC_STACK_ERROR;
1299 OCStackApplicationResult observeResourceCallback(void* ctx,
1300 OCDoHandle /*handle*/,
1301 OCClientResponse* clientResponse)
1303 ClientCallbackContext::ObserveContext* context =
1304 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
1305 OCRepresentation attrs;
1306 HeaderOptions serverHeaderOptions;
1307 uint32_t sequenceNumber = clientResponse->sequenceNumber;
1308 OCStackResult result = clientResponse->result;
1310 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
1313 attrs = parseGetSetCallback(clientResponse);
1315 catch(OC::OCException& e)
1320 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1321 std::thread exec(context->callback, serverHeaderOptions, attrs,
1322 result, sequenceNumber);
1324 if (sequenceNumber == MAX_SEQUENCE_NUMBER + 1)
1326 return OC_STACK_DELETE_TRANSACTION;
1329 return OC_STACK_KEEP_TRANSACTION;
1332 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
1333 const OCDevAddr& devAddr,
1334 const std::string& uri,
1335 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
1336 ObserveCallback& callback, QualityOfService QoS)
1340 return OC_STACK_INVALID_PARAM;
1343 if (headerOptions.size() > MAX_HEADER_OPTIONS)
1345 oclog() << "ObserveResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
1346 return OC_STACK_INVALID_PARAM;
1349 OCStackResult result;
1351 ClientCallbackContext::ObserveContext* ctx =
1352 new ClientCallbackContext::ObserveContext(callback);
1353 OCCallbackData cbdata;
1354 cbdata.context = static_cast<void*>(ctx),
1355 cbdata.cb = observeResourceCallback;
1356 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1360 if (observeType == ObserveType::Observe)
1362 method = OC_REST_OBSERVE;
1364 else if (observeType == ObserveType::ObserveAll)
1366 method = OC_REST_OBSERVE_ALL;
1370 method = OC_REST_OBSERVE_ALL;
1373 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
1375 auto cLock = m_csdkLock.lock();
1379 std::lock_guard<std::recursive_mutex> lock(*cLock);
1380 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
1382 result = OCDoResource(handle, method,
1383 url.c_str(), &devAddr,
1386 static_cast<OCQualityOfService>(QoS),
1389 headerOptions.size());
1395 return OC_STACK_ERROR;
1401 OCStackResult InProcClientWrapper::CancelObserveResource(
1403 const std::string& /*host*/,
1404 const std::string& /*uri*/,
1405 const HeaderOptions& headerOptions,
1406 QualityOfService QoS)
1408 if (headerOptions.size() > MAX_HEADER_OPTIONS)
1410 oclog() << "CancelObserveResource: Header options are more than MAX_HEADER_OPTIONS" << std::flush;
1411 return OC_STACK_INVALID_PARAM;
1414 OCStackResult result;
1415 auto cLock = m_csdkLock.lock();
1419 std::lock_guard<std::recursive_mutex> lock(*cLock);
1420 OCHeaderOption *options = assembleHeaderOptions(headerOptions);
1422 result = OCCancel(handle,
1423 static_cast<OCQualityOfService>(QoS),
1425 headerOptions.size());
1430 result = OC_STACK_ERROR;
1436 OCStackApplicationResult subscribePresenceCallback(void* ctx,
1437 OCDoHandle /*handle*/,
1438 OCClientResponse* clientResponse)
1440 ClientCallbackContext::SubscribePresenceContext* context =
1441 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
1444 * This a hack while we rethink presence subscription.
1446 std::string url = clientResponse->devAddr.addr;
1448 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1449 std::thread exec(context->callback, clientResponse->result,
1450 clientResponse->sequenceNumber, url);
1454 return OC_STACK_KEEP_TRANSACTION;
1457 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
1458 const std::string& host, const std::string& resourceType,
1459 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
1461 if (!presenceHandler)
1463 return OC_STACK_INVALID_PARAM;
1466 ClientCallbackContext::SubscribePresenceContext* ctx =
1467 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
1468 OCCallbackData cbdata;
1469 cbdata.context = static_cast<void*>(ctx),
1470 cbdata.cb = subscribePresenceCallback;
1471 cbdata.cd = [](void* c){delete (ClientCallbackContext::SubscribePresenceContext*)c;};
1474 auto cLock = m_csdkLock.lock();
1476 std::ostringstream os;
1477 os << host << OC_RSRVD_PRESENCE_URI;
1479 if (!resourceType.empty())
1481 os << "?rt=" << resourceType;
1487 return OC_STACK_ERROR;
1490 return OCDoResource(handle, OC_REST_PRESENCE,
1491 os.str().c_str(), nullptr,
1492 nullptr, connectivityType,
1493 OC_LOW_QOS, &cbdata, NULL, 0);
1496 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
1498 OCStackResult result;
1499 auto cLock = m_csdkLock.lock();
1503 std::lock_guard<std::recursive_mutex> lock(*cLock);
1504 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
1508 result = OC_STACK_ERROR;
1515 OCStackResult InProcClientWrapper::SubscribeDevicePresence(OCDoHandle* handle,
1516 const std::string& host,
1517 const std::vector<std::string>& di,
1518 OCConnectivityType connectivityType,
1519 ObserveCallback& callback)
1523 return OC_STACK_INVALID_PARAM;
1525 OCStackResult result;
1527 ClientCallbackContext::ObserveContext* ctx =
1528 new ClientCallbackContext::ObserveContext(callback);
1529 OCCallbackData cbdata;
1530 cbdata.context = static_cast<void*>(ctx),
1531 cbdata.cb = observeResourceCallback;
1532 cbdata.cd = [](void* c){delete (ClientCallbackContext::ObserveContext*)c;};
1534 auto cLock = m_csdkLock.lock();
1538 std::lock_guard<std::recursive_mutex> lock(*cLock);
1540 std::ostringstream os;
1541 os << host << OC_RSRVD_DEVICE_PRESENCE_URI;
1542 QueryParamsList queryParams({{OC_RSRVD_DEVICE_ID, di}});
1543 std::string url = assembleSetResourceUri(os.str(), queryParams);
1545 result = OCDoResource(handle, OC_REST_OBSERVE,
1546 url.c_str(), nullptr,
1547 nullptr, connectivityType,
1548 OC_LOW_QOS, &cbdata,
1554 result = OC_STACK_ERROR;
1561 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
1567 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(const HeaderOptions& headerOptions)
1569 if ( headerOptions.size() == 0)
1574 OCHeaderOption* options = new OCHeaderOption[headerOptions.size()]();
1576 size_t numOptions = 0;
1577 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
1579 OCStackResult ret = OCSetHeaderOption(options, &numOptions, it->getOptionID(),
1580 it->getOptionData().c_str(), it->getOptionData().length());
1581 if (OC_STACK_OK != ret)
1583 OIC_LOG_V(ERROR, TAG, "Failed to convert vnd header options! (error=%d)", ret);
1592 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
1599 OCDPDev_t* result = new OCDPDev_t(*dev);
1600 result->prm = new OCPrm_t[dev->prmLen];
1601 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
1602 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
1605 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
1609 dpList.push_back(cloneDevice(list));
1614 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
1615 GetDirectPairedCallback& callback)
1617 if (!callback || 0 == waittime)
1619 return OC_STACK_INVALID_PARAM;
1622 OCStackResult result = OC_STACK_ERROR;
1623 const OCDPDev_t *list = nullptr;
1624 PairedDevices dpDeviceList;
1626 auto cLock = m_csdkLock.lock();
1630 std::lock_guard<std::recursive_mutex> lock(*cLock);
1632 list = OCDiscoverDirectPairingDevices(waittime);
1635 result = OC_STACK_NO_RESOURCE;
1636 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
1640 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1641 convert(list, dpDeviceList);
1642 std::thread exec(callback, dpDeviceList);
1644 result = OC_STACK_OK;
1649 result = OC_STACK_ERROR;
1655 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
1659 return OC_STACK_INVALID_PARAM;
1662 OCStackResult result = OC_STACK_ERROR;
1663 const OCDPDev_t *list = nullptr;
1664 PairedDevices dpDeviceList;
1666 auto cLock = m_csdkLock.lock();
1670 std::lock_guard<std::recursive_mutex> lock(*cLock);
1672 list = OCGetDirectPairedDevices();
1675 result = OC_STACK_NO_RESOURCE;
1676 OIC_LOG_V(DEBUG, TAG, "%s: No device found for direct pairing", __func__);
1679 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1680 convert(list, dpDeviceList);
1681 std::thread exec(callback, dpDeviceList);
1683 result = OC_STACK_OK;
1688 result = OC_STACK_ERROR;
1694 void directPairingCallback(void *ctx, OCDPDev_t *peer,
1695 OCStackResult result)
1698 ClientCallbackContext::DirectPairingContext* context =
1699 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
1701 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1702 std::thread exec(context->callback, cloneDevice(peer), result);
1706 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
1707 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
1709 if (!peer || !callback)
1711 oclog() << "Invalid parameters" << std::flush;
1712 return OC_STACK_INVALID_PARAM;
1715 OCStackResult result = OC_STACK_ERROR;
1716 ClientCallbackContext::DirectPairingContext* context =
1717 new ClientCallbackContext::DirectPairingContext(callback);
1719 auto cLock = m_csdkLock.lock();
1722 std::lock_guard<std::recursive_mutex> lock(*cLock);
1723 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
1724 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
1729 result = OC_STACK_ERROR;
1734 OCStackApplicationResult KeepAliveRespCallback(void* ctx,
1735 OCDoHandle /*handle*/,
1736 OCClientResponse* clientResponse)
1738 ClientCallbackContext::KeepAliveContext* context =
1739 static_cast<ClientCallbackContext::KeepAliveContext*>(ctx);
1740 OCRepresentation attrs;
1741 OCStackResult result = clientResponse->result;
1745 attrs = parseGetSetCallback(clientResponse);
1747 catch(OC::OCException& e)
1752 OIC_LOG_V(DEBUG, TAG, "%s: call response callback", __func__);
1753 std::thread exec(context->callback, result, attrs);
1755 return OC_STACK_DELETE_TRANSACTION;
1758 OCStackResult InProcClientWrapper::findKeepAliveResource(std::string host,
1759 KeepAliveCallback resultCallback)
1761 if (host.empty() || !resultCallback)
1763 oclog() << "Invalid parameters" << std::flush;
1764 return OC_STACK_INVALID_PARAM;
1767 OCStackResult result = OC_STACK_ERROR;
1769 ClientCallbackContext::KeepAliveContext* ctx =
1770 new ClientCallbackContext::KeepAliveContext(resultCallback);
1771 OCCallbackData cbdata;
1772 cbdata.context = static_cast<void*>(ctx),
1773 cbdata.cb = KeepAliveRespCallback;
1774 cbdata.cd = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
1776 auto cLock = m_csdkLock.lock();
1780 std::lock_guard<std::recursive_mutex> lock(*cLock);
1781 result = OCFindKeepAliveResource(nullptr, host.c_str(), &cbdata);
1786 result = OC_STACK_ERROR;
1791 OCStackResult InProcClientWrapper::sendKeepAliveRequest(std::string host,
1792 const OCRepresentation& rep,
1793 KeepAliveCallback resultCallback)
1795 if (!resultCallback)
1797 oclog() << "Invalid parameters" << std::flush;
1798 return OC_STACK_INVALID_PARAM;
1801 OCStackResult result = OC_STACK_ERROR;
1803 ClientCallbackContext::KeepAliveContext* ctx = new ClientCallbackContext::KeepAliveContext(resultCallback);
1804 OCCallbackData cbdata;
1805 cbdata.context = static_cast<void*>(ctx),
1806 cbdata.cb = KeepAliveRespCallback;
1807 cbdata.cd = [](void* c){delete (ClientCallbackContext::KeepAliveContext*)c;};
1809 auto cLock = m_csdkLock.lock();
1813 std::lock_guard<std::recursive_mutex> lock(*cLock);
1814 OCRepPayload *payload = rep.getPayload();
1815 result = OCSendKeepAliveRequest (nullptr, host.c_str(), (OCPayload*)payload, &cbdata);
1816 if (result != OC_STACK_OK)
1818 OCRepPayloadDestroy(payload);
1824 result = OC_STACK_ERROR;