--- /dev/null
+#ifndef NETWORK_MANAGER_TAG_H
+#define NETWORK_MANAGER_TAG_H
+
+#ifndef TAG
+# define TAG "NetworkManager"
+#endif
+
+#endif // NETWORK_MANAGER_TAG_H
+/**
+ * @brief Policy resource client
+ * @date Created 18.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
#ifndef POLICY_CLIENT_H
#define POLICY_CLIENT_H
*/
class PolicyClient
{
+ static const std::string POLICY_RESOURCE_TYPE;
std::shared_ptr<OC::OCResource> resource;
- std::mutex report_mutex;
- std::condition_variable signal;
- std::string policy;
- bool fired;
- OCStackResult lastResult;
+
public:
/**
* @brief Constructor
+/**
+ * @brief Report resource client
+ * @date Created 18.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
#ifndef REPORT_CLIENT_H
#define REPORT_CLIENT_H
#include <string>
#include <memory>
-#include <mutex>
-#include <condition_variable>
#include <OCApi.h>
#include <OCPlatform.h>
*/
class ReportClient
{
+ static const std::string REPORT_RESOURCE_TYPE;
std::shared_ptr<OC::OCResource> resource;
- std::mutex report_mutex;
- std::condition_variable signal;
- std::string report;
- bool fired;
public:
/**
* @brief Constructor
* @param report [in] report in JSON format
*/
void postReport(const std::string& report);
-private:
- /**
- * @brief foundResourceCb callback processing resource found events
- * @param found_resource [in] found resource
- */
- void foundResourceCb(std::shared_ptr<OC::OCResource> found_resource);
};
} // namespace NetworkManager
--- /dev/null
+/**
+ * @brief Safe iotivity resource callbacks implementation
+ * @date Created 01.06.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
+#ifndef RESOURCE_CALLBACKS_H
+#define RESOURCE_CALLBACKS_H
+
+#include <mutex>
+#include <condition_variable>
+#include <memory>
+#include <OCApi.h>
+#include <OCPlatform.h>
+
+namespace NetworkManager
+{
+
+// Callback wait to finish default time
+const auto DEFAULT_TIMEOUT{std::chrono::seconds(3)};
+
+struct CallbackBase
+{
+ bool fired = false;
+ std::condition_variable signal;
+ std::mutex mtx;
+ std::unique_lock<std::mutex> lock;
+
+ CallbackBase() : mtx(), lock(mtx) {}
+
+ /**
+ * @brief signalize to those who waits for signal
+ */
+ void signalize()
+ {
+ fired = true;
+ signal.notify_one();
+ }
+
+ /**
+ * @brief wait for signal
+ * @return true if callback successfully completed or false if callback not called
+ */
+ bool wait()
+ {
+ signal.wait_for(lock, DEFAULT_TIMEOUT, [this] { return fired; });
+ return fired;
+ }
+};
+
+struct FindResourceCallback : public CallbackBase
+{
+ typedef std::shared_ptr<FindResourceCallback> Sptr;
+
+ std::shared_ptr<OC::OCResource> resource;
+ std::string search_type;
+
+ /**
+ * @brief FindResourceCallback constructor
+ * @param type [in] iotivity resource type to search for
+ */
+ FindResourceCallback(const std::string& type) : CallbackBase(), search_type(type) {}
+
+ /**
+ * @brief call - callback routine, called from iotivity framework
+ * @param ctx [in] this struct self weak reference
+ * @param found_resource [in] resource founded by iotivity
+ */
+ static void call(std::weak_ptr<FindResourceCallback> ctx, std::shared_ptr<OC::OCResource> found_resource);
+};
+
+struct PostResourceCallback : public CallbackBase
+{
+ typedef std::shared_ptr<PostResourceCallback> Sptr;
+
+ /**
+ * @brief call - callback routine, called from iotivity framework
+ * @param ctx [in] this struct self weak reference
+ * @param eCode [in] iotivity callback result code
+ */
+ static void call(std::weak_ptr<PostResourceCallback> ctx, const OC::HeaderOptions & /*ho*/, const OC::OCRepresentation& /*rep*/, const int eCode);
+};
+
+struct GetResourceCallback : public CallbackBase
+{
+ typedef std::shared_ptr<GetResourceCallback> Sptr;
+ OC::OCRepresentation representation;
+
+ /**
+ * @brief call - callback routine, called from iotivity framework
+ * @param ctx [in] this struct self weak reference
+ * @param eCode [in] iotivity callback result code
+ */
+ static void call(std::weak_ptr<GetResourceCallback> ctx, const OC::HeaderOptions & /*ho*/, const OC::OCRepresentation &rep, const int eCode);
+};
+
+/**
+ * @brief bind_callback - helper function to simplify callback binding
+ * @param ptr [in] weak reference to callback struct
+ * @param args [in] arguments to bind
+ */
+template<class Callback, typename... Params>
+auto bind_callback(std::shared_ptr<Callback> ptr, Params&&... args) -> decltype(std::bind(&Callback::call, std::weak_ptr<Callback>(ptr), args...))
+{
+ return std::bind(&Callback::call, std::weak_ptr<Callback>(ptr), args...);
+}
+
+} // namespace NetworkManager
+
+#endif // RESOURCE_CALLBACKS_H
-#if 1
+/**
+ * @brief Policy resource client
+ * @date Created 18.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
#include "policy_client.h"
#include "logging.h"
#include <functional>
#include <chrono>
#include "iotivity.h"
+#include "resource_callbacks.h"
using namespace OC;
namespace NetworkManager
{
-struct FindPolicyCallback
-{
- std::shared_ptr<OCResource> resource;
- bool fired = false;
- std::condition_variable signal;
- std::mutex mtx;
-
- void signalize()
- {
- fired = true;
- signal.notify_one();
- }
-
- static void call(std::weak_ptr<FindPolicyCallback> ctx, std::shared_ptr<OCResource> found_resource)
- {
- if (auto p = ctx.lock())
- {
- std::unique_lock<std::mutex> lock(p->mtx);
-
- if(!p->resource && found_resource)
- {
- for(auto &resource_type : found_resource->getResourceTypes())
- {
- if(resource_type == "core.policy")
- {
- if (found_resource->connectivityType() & OCConnectivityType::CT_ADAPTER_TCP)
- {
- p->resource = found_resource;
- LOG_I(TAG, "Address of selected policy resource: %s", found_resource->host().c_str());
- p->signalize();
- }
- }
- }
- }
- }
- }
-};
-
-struct PostPolicyCallback
-{
- bool fired = false;
- std::condition_variable signal;
- int ecode = 0;
-
- void signalize()
- {
- fired = true;
- signal.notify_one();
- }
-
- static void call(std::weak_ptr<PostPolicyCallback> ctx, const HeaderOptions& hopts, const OCRepresentation& rep, const int eCode)
- {
- if (auto p = ctx.lock())
- {
- LOG_I(TAG, "Post policy return code=%d", eCode);
- p->ecode = eCode;
- p->signalize();
- }
- }
-};
+const std::string PolicyClient::POLICY_RESOURCE_TYPE{"core.policy"};
PolicyClient::PolicyClient(const std::string& host)
{
std::string requestURI{OC_RSRVD_WELL_KNOWN_URI};
- std::shared_ptr<FindPolicyCallback> callback = std::make_shared<FindPolicyCallback>();
- std::unique_lock<std::mutex> lock(callback->mtx);
- OCPlatform::findResource(host, requestURI, CT_DEFAULT, std::bind(&FindPolicyCallback::call, std::weak_ptr<FindPolicyCallback>(callback), PH::_1));
- callback->signal.wait_for(lock, std::chrono::seconds(3));
- if (!callback->fired)
+ FindResourceCallback::Sptr callback = std::make_shared<FindResourceCallback>(POLICY_RESOURCE_TYPE);
+ OCPlatform::findResource(host, requestURI, CT_DEFAULT, bind_callback(callback, PH::_1));
+
+ if (!callback->wait())
{
- LOG_E(TAG, "PolicyClient found callback not called.");
+ LOG_E(TAG, "ReportClient found callback not called.");
}
else
{
return (bool)resource;
}
-struct GetPolicyCallback
-{
- std::string policy;
- bool fired = false;
- std::condition_variable signal;
- std::mutex mtx;
- int ecode = OC_STACK_OK;
-
- void signalize()
- {
- fired = true;
- signal.notify_one();
- }
-
- static void call(std::weak_ptr<GetPolicyCallback> ctx, const HeaderOptions& hopts, const OCRepresentation& rep, const int eCode)
- {
- if (auto p = ctx.lock())
- {
- std::unique_lock<std::mutex> lock(p->mtx);
-
- try
- {
- if(eCode == OC_STACK_OK)
- {
- rep.getValue("policy", p->policy);
- }
- else
- {
- LOG_E(TAG, "Error (PolicyClient::getPolicy): code=%d", eCode);
- p->ecode = eCode;
- }
- }
- catch(std::exception& e)
- {
- LOG_E(TAG, "Exception (PolicyClient::getPolicy): %s", e.what());
- }
-
- p->signalize();
- }
- }
-};
-
std::string PolicyClient::getPolicy(const std::string& did, const std::string& agent)
{
LOG_I(TAG, "PolicyClient::getPolicy(%s, %s)", did.c_str(), agent.c_str());
+ std::string policy;
if(resource)
{
QueryParamsMap query{{"did", did}, {"agent", agent}};
- std::shared_ptr<GetPolicyCallback> callback = std::make_shared<GetPolicyCallback>();
- std::unique_lock<std::mutex> lock(callback->mtx);
+ GetResourceCallback::Sptr callback = std::make_shared<GetResourceCallback>();
- auto result = resource->get(query, std::bind(&GetPolicyCallback::call, std::weak_ptr<GetPolicyCallback>(callback), PH::_1, PH::_2, PH::_3));
+ auto result = resource->get(query, bind_callback(callback, PH::_1, PH::_2, PH::_3));
if (OC_STACK_OK != result)
{
throw IoTInternalError("PolicyClient::getPolicy error", result);
}
- callback->signal.wait_for(lock, std::chrono::seconds(3), [&callback] { return callback->fired; });
-
- if (!callback->fired)
+ if (!callback->wait())
{
throw IoTInternalError("PolicyClient::getPolicy callback not called", EC_UNAUTHORIZED);
}
-
- if (callback->ecode !=OC_STACK_OK)
+ else
{
- throw IoTInternalError("PolicyClient::getPolicy callback error", callback->ecode);
+ callback->representation.getValue("policy", policy);
}
-
- policy = callback->policy;
}
return policy;
repr.setValue("policy", policy);
QueryParamsMap query{{"did", did}, {"agent", agent}};
+ PostResourceCallback::Sptr callback = std::make_shared<PostResourceCallback>();
- std::shared_ptr<PostPolicyCallback> callback = std::make_shared<PostPolicyCallback>();
- std::mutex mtx;
- std::unique_lock<std::mutex> lock(mtx);
-
- auto result = resource->post("core.policy",
+ auto result = resource->post(POLICY_RESOURCE_TYPE,
DEFAULT_INTERFACE,
repr,
query,
- std::bind(&PostPolicyCallback::call, std::weak_ptr<PostPolicyCallback>(callback), PH::_1, PH::_2, PH::_3));
+ bind_callback(callback, PH::_1, PH::_2, PH::_3));
if (OC_STACK_OK != result)
{
- throw IoTInternalError("PolicyClient::postPolicy error", result);
+ throw IoTInternalError("PolicyClient::postPolicy", result);
}
- callback->signal.wait_for(lock, std::chrono::seconds(3), [&callback] { return callback->fired; });
-
- if (!callback->fired)
+ if (!callback->wait())
{
throw IoTInternalError("PolicyClient::postPolicy callback not called", EC_UNAUTHORIZED);
}
- if (OC_STACK_OK != callback->ecode && OC_STACK_RESOURCE_CHANGED != callback->ecode)
- {
- throw IoTInternalError("PolicyClient::postPolicy callback error", callback->ecode);
- }
}
} // namespace NetworkManager
-
-#endif
-
+/**
+ * @brief Report resource client
+ * @date Created 18.05.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
#include "report_client.h"
+#include "network_manager_tag.h"
#include "logging.h"
#include <functional>
#include <chrono>
#include "iotivity.h"
+#include "report_client.h"
+#include "resource_callbacks.h"
using namespace OC;
namespace PH = std::placeholders;
-#define TAG "NetworkManager"
-
namespace NetworkManager
{
+const std::string ReportClient::REPORT_RESOURCE_TYPE{"core.security"};
+
ReportClient::ReportClient(const std::string& host)
{
std::string requestURI{OC_RSRVD_WELL_KNOWN_URI};
- std::unique_lock<std::mutex> lock(report_mutex);
- OCPlatform::findResource(host, requestURI, CT_DEFAULT, std::bind(&ReportClient::foundResourceCb, this, PH::_1));
- signal.wait_for(lock, std::chrono::seconds(3));
+ FindResourceCallback::Sptr callback = std::make_shared<FindResourceCallback>(REPORT_RESOURCE_TYPE);
+
+ OCPlatform::findResource(host, requestURI, CT_DEFAULT, bind_callback(callback, PH::_1));
+
+ if (!callback->wait())
+ {
+ LOG_E(TAG, "ReportClient found callback not called.");
+ }
+ else
+ {
+ resource = callback->resource;
+ }
}
ReportClient::operator bool() const
std::string ReportClient::getReport(const QueryParamsMap& query)
{
std::string report;
- std::unique_lock<std::mutex> lock(report_mutex);
if(resource)
{
- fired = false;
-
- auto result = resource->get(query, [this, &report](const HeaderOptions& hopts, const OCRepresentation& rep, const int eCode)
- {
- try
- {
- if(eCode == OC_STACK_OK)
- {
- rep.getValue("report", report);
- }
- else
- {
- LOG_E(TAG, "Error (ReportClient::getReport): code=%d", eCode);
- }
- }
- catch(std::exception& e)
- {
- LOG_E(TAG, "Exception (ReportClient::getReport): %s", e.what());
- }
-
- fired = true;
- signal.notify_one();
- });
+ GetResourceCallback::Sptr callback = std::make_shared<GetResourceCallback>();
+
+ auto result = resource->get(query, bind_callback(callback, PH::_1, PH::_2, PH::_3));
if (OC_STACK_OK != result)
{
throw IoTInternalError("ReportClient::getReport error", result);
}
- signal.wait_for(lock, std::chrono::seconds(3), [this] { return fired; });
-
- if (!fired)
+ if (!callback->wait())
{
throw IoTInternalError("ReportClient::getReport callback not called", EC_UNAUTHORIZED);
}
+ else
+ {
+ callback->representation.getValue("report", report);
+ }
}
return report;
QueryParamsMap query{{"did", IoTivity::getInstance()->getDeviceID()}};
- std::unique_lock<std::mutex> lock(report_mutex);
+ PostResourceCallback::Sptr callback = std::make_shared<PostResourceCallback>();
- fired = false;
- auto result = resource->post("core.security", DEFAULT_INTERFACE, repr, query,
- [this] (const HeaderOptions & /*ho*/, const OCRepresentation &rep, const int eCode)
- {
- LOG_I(TAG, "post report return code=%d", eCode);
- fired = true;
- signal.notify_one();
- }
- );
+ auto result = resource->post(REPORT_RESOURCE_TYPE,
+ DEFAULT_INTERFACE,
+ repr,
+ query,
+ bind_callback(callback, PH::_1, PH::_2, PH::_3));
if (OC_STACK_OK != result)
{
throw IoTInternalError("ReportClient::postReport error", result);
}
- signal.wait_for(lock, std::chrono::seconds(1), [this] { return fired; });
-
- if (!fired)
+ if (!callback->wait())
{
throw IoTInternalError("ReportClient::postReport callback not called", EC_UNAUTHORIZED);
}
}
-void ReportClient::foundResourceCb(std::shared_ptr<OCResource> found_resource)
-{
- try
- {
- std::unique_lock<std::mutex> lock(report_mutex);
-
- if(!resource && found_resource)
- {
- for(auto &resource_type : found_resource->getResourceTypes())
- {
- if(resource_type == "core.security")
- {
- if (found_resource->connectivityType() & OCConnectivityType::CT_ADAPTER_TCP)
- {
- resource = found_resource;
- LOG_I(TAG, "Address of selected report resource: %s", found_resource->host().c_str());
- signal.notify_one();
- }
- }
- }
- }
-
- }
- catch(std::exception& e)
- {
- LOG_E(TAG, "Exception in foundResource: %s", e.what());
- }
-}
-
} // namespace NetworkManager
--- /dev/null
+/**
+ * @brief Safe iotivity resource callbacks implementation
+ * @date Created 01.06.2017
+ * @author Created 2017 in Samsung Ukraine R&D Center (SURC) under a contract
+ * between LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine)
+ * and "Samsung Electronics Co", Ltd (Seoul, Republic of Korea).
+ * Copyright: (c) Samsung Electronics Co, Ltd 2017. All rights reserved.
+ * @author Mail to: <A HREF="mailto:d.lomtev@samsung.com">Dmytro Lomtev, d.lomtev@samsung.com</A>
+ */
+#include "resource_callbacks.h"
+#include <chrono>
+#include <functional>
+#include <memory>
+#include "logging.h"
+#include "network_manager_tag.h"
+
+namespace NetworkManager
+{
+
+void FindResourceCallback::call(std::weak_ptr<FindResourceCallback> ctx, std::shared_ptr<OC::OCResource> found_resource)
+{
+ if (auto p = ctx.lock())
+ {
+ std::unique_lock<std::mutex> ilock(p->mtx);
+
+ if(!p->resource && found_resource && (found_resource->connectivityType() & OCConnectivityType::CT_ADAPTER_TCP))
+ {
+ for(auto &resource_type : found_resource->getResourceTypes())
+ {
+ if(resource_type == p->search_type)
+ {
+ p->resource = found_resource;
+ LOG_D(TAG, "Address of selected resource of type \"%s\" is %s", p->search_type.c_str(), found_resource->host().c_str());
+ p->signalize();
+ }
+ }
+ }
+ }
+}
+
+void PostResourceCallback::call(std::weak_ptr<PostResourceCallback> ctx, const OC::HeaderOptions & /*ho*/, const OC::OCRepresentation& /*rep*/, const int eCode)
+{
+ if (auto p = ctx.lock())
+ {
+ LOG_D(TAG, "Post callback return code=%d", eCode);
+ p->signalize();
+ }
+}
+
+void GetResourceCallback::call(std::weak_ptr<GetResourceCallback> ctx, const OC::HeaderOptions & /*ho*/, const OC::OCRepresentation &rep, const int eCode)
+{
+ if (auto p = ctx.lock())
+ {
+ try
+ {
+ if(eCode == OC_STACK_OK)
+ {
+ p->representation = rep;
+ }
+ else
+ {
+ LOG_E(TAG, "GetCallback error: code=%d", eCode);
+ }
+ }
+ catch(std::exception& e)
+ {
+ LOG_E(TAG, "GetCallback exception: %s", e.what());
+ }
+ p->signalize();
+ }
+}
+
+} // namespace NetworkManager
+