#include "iotcon/iotcon_instance.h"
+#include <algorithm>
+#include <mutex>
#include <thread>
+#include <vector>
#include "common/logger.h"
#include "common/scope_exit.h"
struct CallbackData {
common::PostCallback fun;
+ CallbackData(common::PostCallback f) {
+ fun = f;
+ }
};
struct CallbackData2 {
return static_cast<long long>(args.find(kId)->second.get<double>());
}
+// CallbackDataManager was created to prevent crash that may occur when
+// the same callback will be called twice in RemoteResourceResponseCallback
+// (The native api allow that same callback will be called more than once)
+class CallbackDataManager {
+ public:
+ static CallbackDataManager* GetInstance();
+ void Add(CallbackData* data);
+ bool IfExists(CallbackData* data);
+
+ private:
+ CallbackDataManager() {};
+ CallbackDataManager(const CallbackDataManager &) = delete;
+ CallbackDataManager(const CallbackDataManager &&) = delete;
+ CallbackDataManager& operator=(const CallbackDataManager &) = delete;
+ CallbackDataManager& operator=(const CallbackDataManager &&) = delete;
+ ~CallbackDataManager() {};
+ std::vector<CallbackData*> callback_;
+ std::mutex callback_mtx_;
+};
+
+CallbackDataManager* CallbackDataManager::GetInstance() {
+ ScopeLogger();
+ static CallbackDataManager instance;
+ return &instance;
+}
+
+void CallbackDataManager::Add(CallbackData* data) {
+ ScopeLogger();
+ std::lock_guard<std::mutex> lock(callback_mtx_);
+ callback_.push_back(data);
+}
+
+bool CallbackDataManager::IfExists(CallbackData* data) {
+ ScopeLogger();
+ std::lock_guard<std::mutex> lock(callback_mtx_);
+ std::vector<CallbackData*>::iterator it;
+ it = find(callback_.begin(), callback_.end(), data);
+ return (it != callback_.end());
+}
+
void RemoteResourceResponseCallback(iotcon_remote_resource_h resource, iotcon_error_e err,
iotcon_request_type_e request_type, iotcon_response_h response,
void* user_data) {
switch (err) {
case IOTCON_ERROR_NONE:
ret = IotconUtils::ResponseToJson(response, &value.get<picojson::object>());
+ if (CallbackDataManager::GetInstance()->IfExists(data.get())) {
+ LoggerD("user_data was called earlier, so ignore.");
+ data.release();
+ return;
+ }
break;
case IOTCON_ERROR_TIMEOUT:
- LoggerD("IOTCON_TIMEOUT ");
+ LoggerD("IOTCON_TIMEOUT");
+ ret = IotconUtils::ConvertIotconError(err);
+ if (CallbackDataManager::GetInstance()->IfExists(data.get())) {
+ LoggerD("user_data was called earlier, so ignore.");
+ data.release();
+ return;
+ }
+ break;
default:
ret = IotconUtils::ConvertIotconError(err);
+ if (CallbackDataManager::GetInstance()->IfExists(data.get())) {
+ LoggerD("user_data was called earlier, so ignore.");
+ data.release();
+ return;
+ }
+ break;
}
+ CallbackDataManager::GetInstance()->Add(data.get());
data->fun(ret, value);
} else {
LoggerE("Native callback data is null");