1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #include "InProcClientWrapper.h"
24 #include "OCPlatform.h"
25 #include "OCResource.h"
26 #include "ocpayload.h"
27 #include <OCSerialization.h>
32 InProcClientWrapper::InProcClientWrapper(
33 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
34 : m_threadRun(false), m_csdkLock(csdkLock),
37 // if the config type is server, we ought to never get called. If the config type
38 // is both, we count on the server to run the thread and do the initialize
40 if (m_cfg.mode == ModeType::Client)
42 OCTransportFlags serverFlags =
43 static_cast<OCTransportFlags>(m_cfg.serverConnectivity & CT_MASK_FLAGS);
44 OCTransportFlags clientFlags =
45 static_cast<OCTransportFlags>(m_cfg.clientConnectivity & CT_MASK_FLAGS);
46 OCStackResult result = OCInit1(OC_CLIENT, serverFlags, clientFlags);
48 if (OC_STACK_OK != result)
50 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
54 m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
58 InProcClientWrapper::~InProcClientWrapper()
60 if (m_threadRun && m_listeningThread.joinable())
63 m_listeningThread.join();
66 // only stop if we are the ones who actually called 'init'. We are counting
67 // on the server to do the stop.
68 if (m_cfg.mode == ModeType::Client)
74 void InProcClientWrapper::listeningFunc()
79 auto cLock = m_csdkLock.lock();
82 std::lock_guard<std::recursive_mutex> lock(*cLock);
87 result = OC_STACK_ERROR;
90 if (result != OC_STACK_OK)
92 // TODO: do something with result if failed?
95 // To minimize CPU utilization we may wish to do this with sleep
96 std::this_thread::sleep_for(std::chrono::milliseconds(10));
100 OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
102 if (clientResponse->payload == nullptr ||
104 clientResponse->payload->type != PAYLOAD_TYPE_DEVICE &&
105 clientResponse->payload->type != PAYLOAD_TYPE_PLATFORM &&
106 clientResponse->payload->type != PAYLOAD_TYPE_REPRESENTATION
110 //OCPayloadDestroy(clientResponse->payload);
111 return OCRepresentation();
115 oc.setPayload(clientResponse->payload);
116 //OCPayloadDestroy(clientResponse->payload);
118 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
119 if (it == oc.representations().end())
121 return OCRepresentation();
124 // first one is considered the root, everything else is considered a child of this one.
125 OCRepresentation root = *it;
126 root.setDevAddr(clientResponse->devAddr);
127 root.setUri(clientResponse->resourceUri);
130 std::for_each(it, oc.representations().end(),
131 [&root](const OCRepresentation& repItr)
132 {root.addChild(repItr);});
137 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle /*handle*/,
138 OCClientResponse* clientResponse)
140 ClientCallbackContext::ListenContext* context =
141 static_cast<ClientCallbackContext::ListenContext*>(ctx);
143 if (clientResponse->result != OC_STACK_OK)
145 oclog() << "listenCallback(): failed to create resource. clientResponse: "
146 << clientResponse->result
149 return OC_STACK_KEEP_TRANSACTION;
152 if (!clientResponse->payload || clientResponse->payload->type != PAYLOAD_TYPE_DISCOVERY)
154 oclog() << "listenCallback(): clientResponse payload was null or the wrong type"
156 return OC_STACK_KEEP_TRANSACTION;
159 auto clientWrapper = context->clientWrapper.lock();
163 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
165 return OC_STACK_KEEP_TRANSACTION;
169 ListenOCContainer container(clientWrapper, clientResponse->devAddr,
170 reinterpret_cast<OCDiscoveryPayload*>(clientResponse->payload));
171 // 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){
179 oclog() << "Exception in listCallback, ignoring response: "
180 << e.what() << std::flush;
184 return OC_STACK_KEEP_TRANSACTION;
187 OCStackResult InProcClientWrapper::ListenForResource(
188 const std::string& serviceUrl,
189 const std::string& resourceType,
190 OCConnectivityType connectivityType,
191 FindCallback& callback, QualityOfService QoS)
195 return OC_STACK_INVALID_PARAM;
198 OCStackResult result;
199 ostringstream resourceUri;
200 resourceUri << serviceUrl << resourceType;
202 ClientCallbackContext::ListenContext* context =
203 new ClientCallbackContext::ListenContext(callback, shared_from_this());
204 OCCallbackData cbdata(
205 static_cast<void*>(context),
207 [](void* c){delete static_cast<ClientCallbackContext::ListenContext*>(c);}
210 auto cLock = m_csdkLock.lock();
213 std::lock_guard<std::recursive_mutex> lock(*cLock);
214 result = OCDoResource(nullptr, OC_REST_DISCOVER,
215 resourceUri.str().c_str(),
216 nullptr, nullptr, connectivityType,
217 static_cast<OCQualityOfService>(QoS),
224 result = OC_STACK_ERROR;
229 OCStackApplicationResult listenDeviceCallback(void* ctx,
230 OCDoHandle /*handle*/,
231 OCClientResponse* clientResponse)
233 ClientCallbackContext::DeviceListenContext* context =
234 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
238 OCRepresentation rep = parseGetSetCallback(clientResponse);
239 std::thread exec(context->callback, rep);
242 catch(OC::OCException& e)
244 oclog() <<"Exception in listenDeviceCallback, ignoring response: "
245 <<e.what() <<std::flush;
248 return OC_STACK_KEEP_TRANSACTION;
251 OCStackResult InProcClientWrapper::ListenForDevice(
252 const std::string& serviceUrl,
253 const std::string& deviceURI,
254 OCConnectivityType connectivityType,
255 FindDeviceCallback& callback,
256 QualityOfService QoS)
260 return OC_STACK_INVALID_PARAM;
262 OCStackResult result;
263 ostringstream deviceUri;
264 deviceUri << serviceUrl << deviceURI;
266 ClientCallbackContext::DeviceListenContext* context =
267 new ClientCallbackContext::DeviceListenContext(callback, shared_from_this());
268 OCCallbackData cbdata(
269 static_cast<void*>(context),
270 listenDeviceCallback,
271 [](void* c){delete static_cast<ClientCallbackContext::DeviceListenContext*>(c);}
274 auto cLock = m_csdkLock.lock();
277 std::lock_guard<std::recursive_mutex> lock(*cLock);
278 result = OCDoResource(nullptr, OC_REST_DISCOVER,
279 deviceUri.str().c_str(),
280 nullptr, nullptr, connectivityType,
281 static_cast<OCQualityOfService>(QoS),
288 result = OC_STACK_ERROR;
293 void parseServerHeaderOptions(OCClientResponse* clientResponse,
294 HeaderOptions& serverHeaderOptions)
298 // Parse header options from server
300 std::string optionData;
302 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
304 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
305 optionData = reinterpret_cast<const char*>
306 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
307 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
308 serverHeaderOptions.push_back(headerOption);
313 // clientResponse is invalid
314 // TODO check proper logging
315 std::cout << " Invalid response " << std::endl;
319 OCStackApplicationResult getResourceCallback(void* ctx,
320 OCDoHandle /*handle*/,
321 OCClientResponse* clientResponse)
323 ClientCallbackContext::GetContext* context =
324 static_cast<ClientCallbackContext::GetContext*>(ctx);
326 OCRepresentation rep;
327 HeaderOptions serverHeaderOptions;
328 OCStackResult result = clientResponse->result;
329 if (result == OC_STACK_OK)
331 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
334 rep = parseGetSetCallback(clientResponse);
336 catch(OC::OCException& e)
342 std::thread exec(context->callback, serverHeaderOptions, rep, result);
344 return OC_STACK_DELETE_TRANSACTION;
347 OCStackResult InProcClientWrapper::GetResourceRepresentation(
348 const OCDevAddr& devAddr,
349 const std::string& resourceUri,
350 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
351 GetCallback& callback, QualityOfService QoS)
355 return OC_STACK_INVALID_PARAM;
357 OCStackResult result;
358 ClientCallbackContext::GetContext* ctx =
359 new ClientCallbackContext::GetContext(callback);
360 OCCallbackData cbdata(
361 static_cast<void*>(ctx),
363 [](void* c){delete static_cast<ClientCallbackContext::GetContext*>(c);}
366 std::string uri = assembleSetResourceUri(resourceUri, queryParams);
368 auto cLock = m_csdkLock.lock();
372 std::lock_guard<std::recursive_mutex> lock(*cLock);
373 OCHeaderOption options[MAX_HEADER_OPTIONS];
375 result = OCDoResource(
376 nullptr, OC_REST_GET,
380 static_cast<OCQualityOfService>(QoS),
382 assembleHeaderOptions(options, headerOptions),
383 headerOptions.size());
388 result = OC_STACK_ERROR;
394 OCStackApplicationResult setResourceCallback(void* ctx,
395 OCDoHandle /*handle*/,
396 OCClientResponse* clientResponse)
398 ClientCallbackContext::SetContext* context =
399 static_cast<ClientCallbackContext::SetContext*>(ctx);
400 OCRepresentation attrs;
401 HeaderOptions serverHeaderOptions;
403 OCStackResult result = clientResponse->result;
404 if (OC_STACK_OK == result ||
405 OC_STACK_RESOURCE_CREATED == result ||
406 OC_STACK_RESOURCE_DELETED == result ||
407 OC_STACK_RESOURCE_CHANGED == result)
409 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
412 attrs = parseGetSetCallback(clientResponse);
414 catch(OC::OCException& e)
420 std::thread exec(context->callback, serverHeaderOptions, attrs, result);
422 return OC_STACK_DELETE_TRANSACTION;
425 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
426 const QueryParamsMap& queryParams)
428 if (uri.back() == '/')
430 uri.resize(uri.size()-1);
433 ostringstream paramsList;
434 if (queryParams.size() > 0)
439 for(auto& param : queryParams)
441 paramsList << param.first <<'='<<param.second<<';';
444 std::string queryString = paramsList.str();
445 if (queryString.back() == ';')
447 queryString.resize(queryString.size() - 1);
450 std::string ret = uri + queryString;
454 OCPayload* InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
456 MessageContainer ocInfo;
457 ocInfo.addRepresentation(rep);
458 for(const OCRepresentation& r : rep.getChildren())
460 ocInfo.addRepresentation(r);
463 return reinterpret_cast<OCPayload*>(ocInfo.getPayload());
466 OCStackResult InProcClientWrapper::PostResourceRepresentation(
467 const OCDevAddr& devAddr,
468 const std::string& uri,
469 const OCRepresentation& rep,
470 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
471 PostCallback& callback, QualityOfService QoS)
475 return OC_STACK_INVALID_PARAM;
477 OCStackResult result;
478 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
479 OCCallbackData cbdata(
480 static_cast<void*>(ctx),
482 [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);}
485 std::string url = assembleSetResourceUri(uri, queryParams);
487 auto cLock = m_csdkLock.lock();
491 std::lock_guard<std::recursive_mutex> lock(*cLock);
492 OCHeaderOption options[MAX_HEADER_OPTIONS];
494 result = OCDoResource(nullptr, OC_REST_POST,
495 url.c_str(), &devAddr,
496 assembleSetResourcePayload(rep),
498 static_cast<OCQualityOfService>(QoS),
500 assembleHeaderOptions(options, headerOptions),
501 headerOptions.size());
506 result = OC_STACK_ERROR;
512 OCStackResult InProcClientWrapper::PutResourceRepresentation(
513 const OCDevAddr& devAddr,
514 const std::string& uri,
515 const OCRepresentation& rep,
516 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
517 PutCallback& callback, QualityOfService QoS)
521 return OC_STACK_INVALID_PARAM;
523 OCStackResult result;
524 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext(callback);
525 OCCallbackData cbdata(
526 static_cast<void*>(ctx),
528 [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);}
531 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
533 auto cLock = m_csdkLock.lock();
537 std::lock_guard<std::recursive_mutex> lock(*cLock);
539 OCHeaderOption options[MAX_HEADER_OPTIONS];
541 result = OCDoResource(&handle, OC_REST_PUT,
542 url.c_str(), &devAddr,
543 assembleSetResourcePayload(rep),
545 static_cast<OCQualityOfService>(QoS),
547 assembleHeaderOptions(options, headerOptions),
548 headerOptions.size());
553 result = OC_STACK_ERROR;
559 OCStackApplicationResult deleteResourceCallback(void* ctx,
560 OCDoHandle /*handle*/,
561 OCClientResponse* clientResponse)
563 ClientCallbackContext::DeleteContext* context =
564 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
565 HeaderOptions serverHeaderOptions;
567 if (clientResponse->result == OC_STACK_OK)
569 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
571 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
573 return OC_STACK_DELETE_TRANSACTION;
576 OCStackResult InProcClientWrapper::DeleteResource(
577 const OCDevAddr& devAddr,
578 const std::string& uri,
579 const HeaderOptions& headerOptions,
580 DeleteCallback& callback,
581 QualityOfService /*QoS*/)
585 return OC_STACK_INVALID_PARAM;
587 OCStackResult result;
588 ClientCallbackContext::DeleteContext* ctx =
589 new ClientCallbackContext::DeleteContext(callback);
590 OCCallbackData cbdata(
591 static_cast<void*>(ctx),
592 deleteResourceCallback,
593 [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);}
596 auto cLock = m_csdkLock.lock();
600 OCHeaderOption options[MAX_HEADER_OPTIONS];
602 std::lock_guard<std::recursive_mutex> lock(*cLock);
604 result = OCDoResource(nullptr, OC_REST_DELETE,
605 uri.c_str(), &devAddr,
608 static_cast<OCQualityOfService>(m_cfg.QoS),
610 assembleHeaderOptions(options, headerOptions),
611 headerOptions.size());
616 result = OC_STACK_ERROR;
622 OCStackApplicationResult observeResourceCallback(void* ctx,
623 OCDoHandle /*handle*/,
624 OCClientResponse* clientResponse)
626 ClientCallbackContext::ObserveContext* context =
627 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
628 OCRepresentation attrs;
629 HeaderOptions serverHeaderOptions;
630 uint32_t sequenceNumber = clientResponse->sequenceNumber;
631 OCStackResult result = clientResponse->result;
632 if (clientResponse->result == OC_STACK_OK)
634 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
637 attrs = parseGetSetCallback(clientResponse);
639 catch(OC::OCException& e)
644 std::thread exec(context->callback, serverHeaderOptions, attrs,
645 result, sequenceNumber);
648 return OC_STACK_KEEP_TRANSACTION;
651 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
652 const OCDevAddr& devAddr,
653 const std::string& uri,
654 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
655 ObserveCallback& callback, QualityOfService QoS)
659 return OC_STACK_INVALID_PARAM;
661 OCStackResult result;
663 ClientCallbackContext::ObserveContext* ctx =
664 new ClientCallbackContext::ObserveContext(callback);
665 OCCallbackData cbdata(
666 static_cast<void*>(ctx),
667 observeResourceCallback,
668 [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);}
672 if (observeType == ObserveType::Observe)
674 method = OC_REST_OBSERVE;
676 else if (observeType == ObserveType::ObserveAll)
678 method = OC_REST_OBSERVE_ALL;
682 method = OC_REST_OBSERVE_ALL;
685 std::string url = assembleSetResourceUri(uri, queryParams).c_str();
687 auto cLock = m_csdkLock.lock();
691 std::lock_guard<std::recursive_mutex> lock(*cLock);
692 OCHeaderOption options[MAX_HEADER_OPTIONS];
694 result = OCDoResource(handle, method,
695 url.c_str(), &devAddr,
698 static_cast<OCQualityOfService>(QoS),
700 assembleHeaderOptions(options, headerOptions),
701 headerOptions.size());
706 return OC_STACK_ERROR;
712 OCStackResult InProcClientWrapper::CancelObserveResource(
714 const std::string& /*host*/,
715 const std::string& /*uri*/,
716 const HeaderOptions& headerOptions,
717 QualityOfService QoS)
719 OCStackResult result;
720 auto cLock = m_csdkLock.lock();
724 std::lock_guard<std::recursive_mutex> lock(*cLock);
725 OCHeaderOption options[MAX_HEADER_OPTIONS];
727 result = OCCancel(handle,
728 static_cast<OCQualityOfService>(QoS),
729 assembleHeaderOptions(options, headerOptions),
730 headerOptions.size());
734 result = OC_STACK_ERROR;
740 OCStackApplicationResult subscribePresenceCallback(void* ctx,
741 OCDoHandle /*handle*/,
742 OCClientResponse* clientResponse)
744 ClientCallbackContext::SubscribePresenceContext* context =
745 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
748 * This a hack while we rethink presence subscription.
750 std::string url = clientResponse->devAddr.addr;
752 std::thread exec(context->callback, clientResponse->result,
753 clientResponse->sequenceNumber, url);
757 return OC_STACK_KEEP_TRANSACTION;
760 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
761 const std::string& host, const std::string& resourceType,
762 OCConnectivityType connectivityType, SubscribeCallback& presenceHandler)
764 if (!presenceHandler)
766 return OC_STACK_INVALID_PARAM;
769 ClientCallbackContext::SubscribePresenceContext* ctx =
770 new ClientCallbackContext::SubscribePresenceContext(presenceHandler);
771 OCCallbackData cbdata(
772 static_cast<void*>(ctx),
773 subscribePresenceCallback,
775 {delete static_cast<ClientCallbackContext::SubscribePresenceContext*>(c);}
778 auto cLock = m_csdkLock.lock();
780 std::ostringstream os;
781 os << host << OC_RSRVD_PRESENCE_URI;
783 if (!resourceType.empty())
785 os << "?rt=" << resourceType;
791 return OC_STACK_ERROR;
794 return OCDoResource(handle, OC_REST_PRESENCE,
795 os.str().c_str(), nullptr,
796 nullptr, connectivityType,
797 OC_LOW_QOS, &cbdata, NULL, 0);
800 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
802 OCStackResult result;
803 auto cLock = m_csdkLock.lock();
807 std::lock_guard<std::recursive_mutex> lock(*cLock);
808 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
812 result = OC_STACK_ERROR;
818 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
824 OCHeaderOption* InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
825 const HeaderOptions& headerOptions)
829 if ( headerOptions.size() == 0)
834 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
836 options[i] = OCHeaderOption(OC_COAP_ID,
838 it->getOptionData().length() + 1,
839 reinterpret_cast<const uint8_t*>(it->getOptionData().c_str()));
846 std::shared_ptr<OCDirectPairing> cloneDevice(const OCDPDev_t* dev)
853 OCDPDev_t* result = new OCDPDev_t(*dev);
854 result->prm = new OCPrm_t[dev->prmLen];
855 memcpy(result->prm, dev->prm, sizeof(OCPrm_t)*dev->prmLen);
856 return std::shared_ptr<OCDirectPairing>(new OCDirectPairing(result));
859 void InProcClientWrapper::convert(const OCDPDev_t *list, PairedDevices& dpList)
863 dpList.push_back(cloneDevice(list));
868 OCStackResult InProcClientWrapper::FindDirectPairingDevices(unsigned short waittime,
869 GetDirectPairedCallback& callback)
871 if (!callback || 0 == waittime)
873 return OC_STACK_INVALID_PARAM;
876 OCStackResult result = OC_STACK_ERROR;
877 const OCDPDev_t *list = nullptr;
878 PairedDevices dpDeviceList;
880 auto cLock = m_csdkLock.lock();
884 std::lock_guard<std::recursive_mutex> lock(*cLock);
886 list = OCDiscoverDirectPairingDevices(waittime);
889 result = OC_STACK_NO_RESOURCE;
890 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
894 convert(list, dpDeviceList);
895 std::thread exec(callback, dpDeviceList);
897 result = OC_STACK_OK;
902 result = OC_STACK_ERROR;
908 OCStackResult InProcClientWrapper::GetDirectPairedDevices(GetDirectPairedCallback& callback)
912 return OC_STACK_INVALID_PARAM;
915 OCStackResult result = OC_STACK_ERROR;
916 const OCDPDev_t *list = nullptr;
917 PairedDevices dpDeviceList;
919 auto cLock = m_csdkLock.lock();
923 std::lock_guard<std::recursive_mutex> lock(*cLock);
925 list = OCGetDirectPairedDevices();
928 result = OC_STACK_NO_RESOURCE;
929 oclog() << "findDirectPairingDevices(): No device found for direct pairing"
933 convert(list, dpDeviceList);
934 std::thread exec(callback, dpDeviceList);
936 result = OC_STACK_OK;
941 result = OC_STACK_ERROR;
947 void directPairingCallback(void *ctx, OCDPDev_t *peer,
948 OCStackResult result)
951 ClientCallbackContext::DirectPairingContext* context =
952 static_cast<ClientCallbackContext::DirectPairingContext*>(ctx);
954 std::thread exec(context->callback, cloneDevice(peer), result);
958 OCStackResult InProcClientWrapper::DoDirectPairing(std::shared_ptr<OCDirectPairing> peer,
959 const OCPrm_t& pmSel, const std::string& pinNumber, DirectPairingCallback& callback)
961 if (!peer || !callback)
963 oclog() << "Invalid parameters" << std::flush;
964 return OC_STACK_INVALID_PARAM;
967 OCStackResult result = OC_STACK_ERROR;
968 ClientCallbackContext::DirectPairingContext* context =
969 new ClientCallbackContext::DirectPairingContext(callback);
971 auto cLock = m_csdkLock.lock();
974 std::lock_guard<std::recursive_mutex> lock(*cLock);
975 result = OCDoDirectPairing(static_cast<void*>(context), peer->getDev(),
976 pmSel, const_cast<char*>(pinNumber.c_str()), directPairingCallback);
981 result = OC_STACK_ERROR;