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 <OCSerialization.h>
31 InProcClientWrapper::InProcClientWrapper(
32 std::weak_ptr<std::recursive_mutex> csdkLock, PlatformConfig cfg)
33 : m_threadRun(false), m_csdkLock(csdkLock),
36 // if the config type is server, we ought to never get called. If the config type
37 // is both, we count on the server to run the thread and do the initialize
39 if(m_cfg.mode == ModeType::Client)
41 OCStackResult result = OCInit(m_cfg.ipAddress.c_str(), m_cfg.port, OC_CLIENT);
43 if(OC_STACK_OK != result)
45 throw InitializeException(OC::InitException::STACK_INIT_ERROR, result);
49 m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
53 InProcClientWrapper::~InProcClientWrapper()
55 if(m_threadRun && m_listeningThread.joinable())
58 m_listeningThread.join();
61 // only stop if we are the ones who actually called 'init'. We are counting
62 // on the server to do the stop.
63 if(m_cfg.mode == ModeType::Client)
69 void InProcClientWrapper::listeningFunc()
74 auto cLock = m_csdkLock.lock();
77 std::lock_guard<std::recursive_mutex> lock(*cLock);
82 result = OC_STACK_ERROR;
85 if(result != OC_STACK_OK)
87 // TODO: do something with result if failed?
90 // To minimize CPU utilization we may wish to do this with sleep
91 std::this_thread::sleep_for(std::chrono::milliseconds(10));
95 OCRepresentation parseGetSetCallback(OCClientResponse* clientResponse)
97 if(clientResponse->resJSONPayload == nullptr || clientResponse->resJSONPayload[0] == '\0')
99 throw OCException(OC::Exception::STR_NULL_RESPONSE, OC_STACK_ERROR);
103 oc.setJSONRepresentation(clientResponse->resJSONPayload);
105 std::vector<OCRepresentation>::const_iterator it = oc.representations().begin();
106 if(it == oc.representations().end())
108 throw OCException(OC::Exception::INVALID_REPRESENTATION, OC_STACK_ERROR);
111 // first one is considered the root, everything else is considered a child of this one.
112 OCRepresentation root = *it;
115 std::for_each(it, oc.representations().end(),
116 [&root](const OCRepresentation& repItr)
117 {root.addChild(repItr);});
122 OCStackApplicationResult listenCallback(void* ctx, OCDoHandle handle,
123 OCClientResponse* clientResponse)
125 ClientCallbackContext::ListenContext* context =
126 static_cast<ClientCallbackContext::ListenContext*>(ctx);
128 if(clientResponse->result != OC_STACK_OK)
130 oclog() << "listenCallback(): failed to create resource. clientResponse: "
131 << clientResponse->result
134 return OC_STACK_KEEP_TRANSACTION;
137 auto clientWrapper = context->clientWrapper.lock();
141 oclog() << "listenCallback(): failed to get a shared_ptr to the client wrapper"
143 return OC_STACK_KEEP_TRANSACTION;
146 std::stringstream requestStream;
147 requestStream << clientResponse->resJSONPayload;
151 ListenOCContainer container(clientWrapper, *clientResponse->addr,
154 // loop to ensure valid construction of all resources
155 for(auto resource : container.Resources())
157 std::thread exec(context->callback, resource);
162 catch(const std::exception& e)
164 oclog() << "listenCallback failed to parse a malformed message: "
166 << std::endl <<std::endl
167 << clientResponse->result
169 return OC_STACK_KEEP_TRANSACTION;
172 return OC_STACK_KEEP_TRANSACTION;
176 OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl,
177 const std::string& resourceType, uint8_t connectivityType,
178 FindCallback& callback, QualityOfService QoS)
180 OCStackResult InProcClientWrapper::ListenForResource(const std::string& serviceUrl,
181 const std::string& resourceType, FindCallback& callback, QualityOfService QoS)
184 OCStackResult result;
186 OCCallbackData cbdata = {0};
188 ClientCallbackContext::ListenContext* context = new ClientCallbackContext::ListenContext();
189 context->callback = callback;
190 context->clientWrapper = shared_from_this();
192 cbdata.context = static_cast<void*>(context);
193 cbdata.cb = listenCallback;
194 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ListenContext*>(c);};
196 auto cLock = m_csdkLock.lock();
199 std::lock_guard<std::recursive_mutex> lock(*cLock);
202 result = OCDoResource(&handle, OC_REST_GET,
203 resourceType.c_str(),
204 nullptr, nullptr, connectivityType,
205 static_cast<OCQualityOfService>(QoS),
209 result = OCDoResource(&handle, OC_REST_GET,
210 resourceType.c_str(),
212 static_cast<OCQualityOfService>(QoS),
220 result = OC_STACK_ERROR;
225 OCStackApplicationResult listenDeviceCallback(void* ctx, OCDoHandle handle,
226 OCClientResponse* clientResponse)
228 ClientCallbackContext::DeviceListenContext* context =
229 static_cast<ClientCallbackContext::DeviceListenContext*>(ctx);
231 OCRepresentation rep = parseGetSetCallback(clientResponse);
232 std::thread exec(context->callback, rep);
235 return OC_STACK_KEEP_TRANSACTION;
239 OCStackResult InProcClientWrapper::ListenForDevice(const std::string& serviceUrl,
240 const std::string& deviceURI, uint8_t connectivityType,
241 FindDeviceCallback& callback, QualityOfService QoS)
243 OCStackResult InProcClientWrapper::ListenForDevice(const std::string& serviceUrl,
244 const std::string& deviceURI, FindDeviceCallback& callback, QualityOfService QoS)
247 OCStackResult result;
249 OCCallbackData cbdata = {0};
251 ClientCallbackContext::DeviceListenContext* context =
252 new ClientCallbackContext::DeviceListenContext();
253 context->callback = callback;
254 context->clientWrapper = shared_from_this();
256 cbdata.context = static_cast<void*>(context);
257 cbdata.cb = listenDeviceCallback;
258 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::DeviceListenContext*>(c);};
260 auto cLock = m_csdkLock.lock();
263 std::lock_guard<std::recursive_mutex> lock(*cLock);
266 result = OCDoResource(&handle, OC_REST_GET,
268 nullptr, nullptr, connectivityType,
269 static_cast<OCQualityOfService>(QoS),
273 result = OCDoResource(&handle, OC_REST_GET,
276 static_cast<OCQualityOfService>(QoS),
283 result = OC_STACK_ERROR;
288 void parseServerHeaderOptions(OCClientResponse* clientResponse,
289 HeaderOptions& serverHeaderOptions)
293 // Parse header options from server
295 std::string optionData;
297 for(int i = 0; i < clientResponse->numRcvdVendorSpecificHeaderOptions; i++)
299 optionID = clientResponse->rcvdVendorSpecificHeaderOptions[i].optionID;
300 optionData = reinterpret_cast<const char*>
301 (clientResponse->rcvdVendorSpecificHeaderOptions[i].optionData);
302 HeaderOption::OCHeaderOption headerOption(optionID, optionData);
303 serverHeaderOptions.push_back(headerOption);
308 // clientResponse is invalid
309 // TODO check proper logging
310 std::cout << " Invalid response " << std::endl;
314 OCStackApplicationResult getResourceCallback(void* ctx, OCDoHandle handle,
315 OCClientResponse* clientResponse)
317 ClientCallbackContext::GetContext* context =
318 static_cast<ClientCallbackContext::GetContext*>(ctx);
320 OCRepresentation rep;
321 HeaderOptions serverHeaderOptions;
322 if(clientResponse->result == OC_STACK_OK)
324 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
325 rep = parseGetSetCallback(clientResponse);
328 std::thread exec(context->callback, serverHeaderOptions, rep, clientResponse->result);
330 return OC_STACK_DELETE_TRANSACTION;
334 OCStackResult InProcClientWrapper::GetResourceRepresentation(const std::string& host,
335 const std::string& uri, uint8_t connectivityType, const QueryParamsMap& queryParams,
336 const HeaderOptions& headerOptions, GetCallback& callback,
337 QualityOfService QoS)
339 OCStackResult InProcClientWrapper::GetResourceRepresentation(const std::string& host,
340 const std::string& uri, const QueryParamsMap& queryParams,
341 const HeaderOptions& headerOptions, GetCallback& callback,
342 QualityOfService QoS)
345 OCStackResult result;
346 OCCallbackData cbdata = {0};
348 ClientCallbackContext::GetContext* ctx = new ClientCallbackContext::GetContext();
349 ctx->callback = callback;
350 cbdata.context = static_cast<void*>(ctx);
351 cbdata.cb = &getResourceCallback;
352 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::GetContext*>(c);};
354 auto cLock = m_csdkLock.lock();
358 std::ostringstream os;
359 os << host << assembleSetResourceUri(uri, queryParams).c_str();
361 std::lock_guard<std::recursive_mutex> lock(*cLock);
363 OCHeaderOption options[MAX_HEADER_OPTIONS];
365 assembleHeaderOptions(options, headerOptions);
367 result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(),
368 nullptr, nullptr, connectivityType,
369 static_cast<OCQualityOfService>(QoS),
371 options, headerOptions.size());
373 result = OCDoResource(&handle, OC_REST_GET, os.str().c_str(),
375 static_cast<OCQualityOfService>(QoS),
377 options, headerOptions.size());
383 result = OC_STACK_ERROR;
389 OCStackApplicationResult setResourceCallback(void* ctx, OCDoHandle handle,
390 OCClientResponse* clientResponse)
392 ClientCallbackContext::SetContext* context =
393 static_cast<ClientCallbackContext::SetContext*>(ctx);
394 OCRepresentation attrs;
395 HeaderOptions serverHeaderOptions;
397 if (OC_STACK_OK == clientResponse->result ||
398 OC_STACK_RESOURCE_CREATED == clientResponse->result ||
399 OC_STACK_RESOURCE_DELETED == clientResponse->result)
401 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
402 attrs = parseGetSetCallback(clientResponse);
405 std::thread exec(context->callback, serverHeaderOptions, attrs, clientResponse->result);
407 return OC_STACK_DELETE_TRANSACTION;
410 std::string InProcClientWrapper::assembleSetResourceUri(std::string uri,
411 const QueryParamsMap& queryParams)
413 if(uri.back() == '/')
415 uri.resize(uri.size()-1);
418 ostringstream paramsList;
419 if(queryParams.size() > 0)
424 for(auto& param : queryParams)
426 paramsList << param.first <<'='<<param.second<<'&';
429 std::string queryString = paramsList.str();
430 if(queryString.back() == '&')
432 queryString.resize(queryString.size() - 1);
435 std::string ret = uri + queryString;
439 std::string InProcClientWrapper::assembleSetResourcePayload(const OCRepresentation& rep)
441 MessageContainer ocInfo;
442 ocInfo.addRepresentation(rep);
443 return ocInfo.getJSONRepresentation(OCInfoFormat::IncludeOC);
447 OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
448 const std::string& uri, uint8_t connectivityType, const OCRepresentation& rep,
449 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
450 PostCallback& callback, QualityOfService QoS)
452 OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
453 const std::string& uri, const OCRepresentation& rep,
454 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
455 PostCallback& callback, QualityOfService QoS)
458 OCStackResult result;
459 OCCallbackData cbdata = {0};
461 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
462 ctx->callback = callback;
463 cbdata.cb = &setResourceCallback;
464 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
465 cbdata.context = static_cast<void*>(ctx);
467 // TODO: in the future the cstack should be combining these two strings!
469 os << host << assembleSetResourceUri(uri, queryParams).c_str();
470 // TODO: end of above
472 auto cLock = m_csdkLock.lock();
476 std::lock_guard<std::recursive_mutex> lock(*cLock);
477 OCHeaderOption options[MAX_HEADER_OPTIONS];
480 assembleHeaderOptions(options, headerOptions);
482 result = OCDoResource(&handle, OC_REST_POST,
483 os.str().c_str(), nullptr,
484 assembleSetResourcePayload(rep).c_str(), connectivityType,
485 static_cast<OCQualityOfService>(QoS),
486 &cbdata, options, headerOptions.size());
488 result = OCDoResource(&handle, OC_REST_POST,
489 os.str().c_str(), nullptr,
490 assembleSetResourcePayload(rep).c_str(),
491 static_cast<OCQualityOfService>(QoS),
492 &cbdata, options, headerOptions.size());
498 result = OC_STACK_ERROR;
505 OCStackResult InProcClientWrapper::PutResourceRepresentation(const std::string& host,
506 const std::string& uri, uint8_t connectivityType, const OCRepresentation& rep,
507 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
508 PutCallback& callback, QualityOfService QoS)
510 OCStackResult InProcClientWrapper::PutResourceRepresentation(const std::string& host,
511 const std::string& uri, const OCRepresentation& rep,
512 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
513 PutCallback& callback, QualityOfService QoS)
516 OCStackResult result;
517 OCCallbackData cbdata = {0};
519 ClientCallbackContext::SetContext* ctx = new ClientCallbackContext::SetContext();
520 ctx->callback = callback;
521 cbdata.cb = &setResourceCallback;
522 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::SetContext*>(c);};
523 cbdata.context = static_cast<void*>(ctx);
525 // TODO: in the future the cstack should be combining these two strings!
527 os << host << assembleSetResourceUri(uri, queryParams).c_str();
528 // TODO: end of above
530 auto cLock = m_csdkLock.lock();
534 std::lock_guard<std::recursive_mutex> lock(*cLock);
536 OCHeaderOption options[MAX_HEADER_OPTIONS];
538 assembleHeaderOptions(options, headerOptions);
540 result = OCDoResource(&handle, OC_REST_PUT,
541 os.str().c_str(), nullptr,
542 assembleSetResourcePayload(rep).c_str(), connectivityType,
543 static_cast<OCQualityOfService>(QoS),
545 options, headerOptions.size());
547 result = OCDoResource(&handle, OC_REST_PUT,
548 os.str().c_str(), nullptr,
549 assembleSetResourcePayload(rep).c_str(),
550 static_cast<OCQualityOfService>(QoS),
552 options, headerOptions.size());
558 result = OC_STACK_ERROR;
564 OCStackApplicationResult deleteResourceCallback(void* ctx, OCDoHandle handle,
565 OCClientResponse* clientResponse)
567 ClientCallbackContext::DeleteContext* context =
568 static_cast<ClientCallbackContext::DeleteContext*>(ctx);
569 HeaderOptions serverHeaderOptions;
571 if(clientResponse->result == OC_STACK_OK)
573 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
575 std::thread exec(context->callback, serverHeaderOptions, clientResponse->result);
577 return OC_STACK_DELETE_TRANSACTION;
581 OCStackResult InProcClientWrapper::DeleteResource(const std::string& host,
582 const std::string& uri, uint8_t connectivityType, const HeaderOptions& headerOptions,
583 DeleteCallback& callback, QualityOfService QoS)
585 OCStackResult InProcClientWrapper::DeleteResource(const std::string& host,
586 const std::string& uri, const HeaderOptions& headerOptions,
587 DeleteCallback& callback, QualityOfService QoS)
590 OCStackResult result;
591 OCCallbackData cbdata = {0};
593 ClientCallbackContext::DeleteContext* ctx = new ClientCallbackContext::DeleteContext();
594 ctx->callback = callback;
595 cbdata.cb = &deleteResourceCallback;
596 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::DeleteContext*>(c);};
597 cbdata.context = static_cast<void*>(ctx);
602 auto cLock = m_csdkLock.lock();
606 OCHeaderOption options[MAX_HEADER_OPTIONS];
609 assembleHeaderOptions(options, headerOptions);
611 std::lock_guard<std::recursive_mutex> lock(*cLock);
613 result = OCDoResource(&handle, OC_REST_DELETE,
614 os.str().c_str(), nullptr,
615 nullptr, connectivityType,
616 static_cast<OCQualityOfService>(m_cfg.QoS),
617 &cbdata, options, headerOptions.size());
619 result = OCDoResource(&handle, OC_REST_DELETE,
620 os.str().c_str(), nullptr,
621 nullptr, static_cast<OCQualityOfService>(m_cfg.QoS),
622 &cbdata, options, headerOptions.size());
628 result = OC_STACK_ERROR;
634 OCStackApplicationResult observeResourceCallback(void* ctx, OCDoHandle handle,
635 OCClientResponse* clientResponse)
637 ClientCallbackContext::ObserveContext* context =
638 static_cast<ClientCallbackContext::ObserveContext*>(ctx);
639 OCRepresentation attrs;
640 HeaderOptions serverHeaderOptions;
641 uint32_t sequenceNumber = clientResponse->sequenceNumber;
643 if(clientResponse->result == OC_STACK_OK)
645 parseServerHeaderOptions(clientResponse, serverHeaderOptions);
646 attrs = parseGetSetCallback(clientResponse);
648 std::thread exec(context->callback, serverHeaderOptions, attrs,
649 clientResponse->result, sequenceNumber);
651 return OC_STACK_KEEP_TRANSACTION;
655 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
656 const std::string& host, const std::string& uri, uint8_t connectivityType,
657 const QueryParamsMap& queryParams, const HeaderOptions& headerOptions,
658 ObserveCallback& callback, QualityOfService QoS)
660 OCStackResult InProcClientWrapper::ObserveResource(ObserveType observeType, OCDoHandle* handle,
661 const std::string& host, const std::string& uri, const QueryParamsMap& queryParams,
662 const HeaderOptions& headerOptions, ObserveCallback& callback, QualityOfService QoS)
665 OCStackResult result;
666 OCCallbackData cbdata = {0};
668 ClientCallbackContext::ObserveContext* ctx = new ClientCallbackContext::ObserveContext();
669 ctx->callback = callback;
670 cbdata.context = static_cast<void*>(ctx);
671 cbdata.cb = &observeResourceCallback;
672 cbdata.cd = [](void* c){delete static_cast<ClientCallbackContext::ObserveContext*>(c);};
675 if (observeType == ObserveType::Observe)
677 method = OC_REST_OBSERVE;
679 else if (observeType == ObserveType::ObserveAll)
681 method = OC_REST_OBSERVE_ALL;
685 method = OC_REST_OBSERVE_ALL;
688 auto cLock = m_csdkLock.lock();
692 std::ostringstream os;
693 os << host << assembleSetResourceUri(uri, queryParams).c_str();
695 std::lock_guard<std::recursive_mutex> lock(*cLock);
696 OCHeaderOption options[MAX_HEADER_OPTIONS];
698 assembleHeaderOptions(options, headerOptions);
700 result = OCDoResource(handle, method,
701 os.str().c_str(), nullptr,
702 nullptr, connectivityType,
703 static_cast<OCQualityOfService>(QoS),
705 options, headerOptions.size());
707 result = OCDoResource(handle, method,
708 os.str().c_str(), nullptr,
710 static_cast<OCQualityOfService>(QoS),
712 options, headerOptions.size());
718 return OC_STACK_ERROR;
724 OCStackResult InProcClientWrapper::CancelObserveResource(OCDoHandle handle,
725 const std::string& host, const std::string& uri, const HeaderOptions& headerOptions,
726 QualityOfService QoS)
728 OCStackResult result;
729 auto cLock = m_csdkLock.lock();
733 std::lock_guard<std::recursive_mutex> lock(*cLock);
734 OCHeaderOption options[MAX_HEADER_OPTIONS];
736 assembleHeaderOptions(options, headerOptions);
737 result = OCCancel(handle, static_cast<OCQualityOfService>(QoS), options,
738 headerOptions.size());
742 result = OC_STACK_ERROR;
748 OCStackApplicationResult subscribePresenceCallback(void* ctx, OCDoHandle handle,
749 OCClientResponse* clientResponse)
751 char stringAddress[DEV_ADDR_SIZE_MAX];
755 if(OCDevAddrToString(clientResponse->addr, stringAddress) == 0 &&
756 OCDevAddrToPort(clientResponse->addr, &port) == 0)
758 os<<stringAddress<<":"<<port;
760 ClientCallbackContext::SubscribePresenceContext* context =
761 static_cast<ClientCallbackContext::SubscribePresenceContext*>(ctx);
763 std::thread exec(context->callback, clientResponse->result,
764 clientResponse->sequenceNumber, os.str());
770 oclog() << "subscribePresenceCallback(): OCDevAddrToString() or OCDevAddrToPort() "
771 <<"failed"<< std::flush;
773 return OC_STACK_KEEP_TRANSACTION;
777 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
778 const std::string& host, const std::string& resourceType, uint8_t connectivityType,
779 SubscribeCallback& presenceHandler)
781 OCStackResult InProcClientWrapper::SubscribePresence(OCDoHandle* handle,
782 const std::string& host, const std::string& resourceType,
783 SubscribeCallback& presenceHandler)
786 OCCallbackData cbdata = {0};
788 ClientCallbackContext::SubscribePresenceContext* ctx =
789 new ClientCallbackContext::SubscribePresenceContext();
790 ctx->callback = presenceHandler;
791 cbdata.cb = &subscribePresenceCallback;
792 cbdata.context = static_cast<void*>(ctx);
793 cbdata.cd = [](void* c)
794 {delete static_cast<ClientCallbackContext::SubscribePresenceContext*>(c);};
795 auto cLock = m_csdkLock.lock();
797 std::ostringstream os;
798 os << host << "/oc/presence";
800 if(!resourceType.empty())
802 os << "?rt=" << resourceType;
808 return OC_STACK_ERROR;
812 return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
813 connectivityType, OC_LOW_QOS, &cbdata, NULL, 0);
815 return OCDoResource(handle, OC_REST_PRESENCE, os.str().c_str(), nullptr, nullptr,
816 OC_LOW_QOS, &cbdata, NULL, 0);
820 OCStackResult InProcClientWrapper::UnsubscribePresence(OCDoHandle handle)
822 OCStackResult result;
823 auto cLock = m_csdkLock.lock();
827 std::lock_guard<std::recursive_mutex> lock(*cLock);
828 result = OCCancel(handle, OC_LOW_QOS, NULL, 0);
832 result = OC_STACK_ERROR;
838 OCStackResult InProcClientWrapper::GetDefaultQos(QualityOfService& qos)
844 void InProcClientWrapper::assembleHeaderOptions(OCHeaderOption options[],
845 const HeaderOptions& headerOptions)
849 for (auto it=headerOptions.begin(); it != headerOptions.end(); ++it)
851 options[i].protocolID = OC_COAP_ID;
852 options[i].optionID = static_cast<uint16_t>(it->getOptionID());
853 options[i].optionLength = (it->getOptionData()).length() + 1;
854 memcpy(options[i].optionData, (it->getOptionData()).c_str(),
855 (it->getOptionData()).length() + 1);