[NBS] Fix for releasing domains. 14/144714/4
authorSzymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
Tue, 5 Sep 2017 10:31:17 +0000 (12:31 +0200)
committerPiotr Kosko <p.kosko@samsung.com>
Wed, 6 Sep 2017 10:39:16 +0000 (12:39 +0200)
Change-Id: I47a2a86d93e11b6b2f7d02001ec6eda4f65e0b30
Signed-off-by: Tomasz Marciniak <t.marciniak@samsung.com>
Signed-off-by: Szymon Jastrzebski <s.jastrzebsk@partner.samsung.com>
src/networkbearerselection/networkbearerselection_api.js
src/networkbearerselection/networkbearerselection_instance.cc
src/networkbearerselection/networkbearerselection_instance.h
src/networkbearerselection/networkbearerselection_manager.cc
src/networkbearerselection/networkbearerselection_manager.h

index fde026b..f0c3bc1 100644 (file)
@@ -21,7 +21,6 @@ var validator_ = utils_.validator;
 var types_ = validator_.Types;
 var native_ = new xwalk.utils.NativeManager(extension);
 
-
 var NetworkType = {
   CELLULAR: 'CELLULAR',
   UNKNOWN: 'UNKNOWN'
@@ -40,15 +39,15 @@ function _networkBearerSelectionCallback(result) {
   for (id in callbacks) {
     if (callbacks.hasOwnProperty(result.id) && result.id == id) {
       callback = callbacks[id];
-      if (result.state === 'Success') {
+      if (result.status === 'success') {
         native_.callIfPossible(callback.onsuccess);
       }
-      if (result.state === 'Disconnected') {
+
+      if (result.status === 'disconnected') {
         native_.callIfPossible(callback.ondisconnected);
-        native_.removeListener('NetworkBearerSelectionCallback_' + id);
-        delete callbacks[id];
       }
-      if (result.state === 'Error') {
+
+      if (result.status === 'error') {
         native_.callIfPossible(callback.onerror, native_.getErrorObject(result));
         native_.removeListener('NetworkBearerSelectionCallback_' + id);
         delete callbacks[id];
@@ -60,7 +59,7 @@ function _networkBearerSelectionCallback(result) {
 
 function NetworkBearerSelection() {}
 
-NetworkBearerSelection.prototype.requestRouteToHost = function(networkType, domainName, successCallback, errorCallback) {
+NetworkBearerSelection.prototype.requestRouteToHost = function() {
   var args = validator_.validateArgs(arguments, [
     {name: 'networkType', type: types_.ENUM, values: Object.keys(NetworkType)},
     {name: 'domainName', type: types_.STRING},
@@ -90,7 +89,7 @@ NetworkBearerSelection.prototype.requestRouteToHost = function(networkType, doma
   }
 };
 
-NetworkBearerSelection.prototype.releaseRouteToHost = function(networkType, domainName, successCallback, errorCallback) {
+NetworkBearerSelection.prototype.releaseRouteToHost = function() {
   var args = validator_.validateArgs(arguments, [
     {name: 'networkType', type: types_.ENUM, values: Object.keys(NetworkType)},
     {name: 'domainName', type: types_.STRING},
@@ -98,21 +97,24 @@ NetworkBearerSelection.prototype.releaseRouteToHost = function(networkType, doma
     {name: 'errorCallback', type: types_.FUNCTION, optional: true, nullable: true}
   ]);
 
+  var nativeParam = {
+    domainName: args.domainName
+  };
+
   var callback = function(result) {
     if (native_.isFailure(result)) {
       native_.callIfPossible(args.errorCallback, native_.getErrorObject(result));
       return;
     }
 
-    native_.callIfPossible(args.successCallback);
+    args.successCallback();
   };
 
-  var result = native_.call('NetworkBearerSelection_releaseRouteToHost', args, callback);
+  var result = native_.call('NetworkBearerSelection_releaseRouteToHost', nativeParam, callback);
 
   if (native_.isFailure(result)) {
     throw native_.getErrorObject(result);
   }
 };
 
-
 exports = new NetworkBearerSelection();
index babbebf..e8f0bd6 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <functional>
 
+#include "networkbearerselection_manager.h"
 #include "common/picojson.h"
 #include "common/logger.h"
 #include "common/platform_exception.h"
@@ -28,18 +29,19 @@ namespace extension {
 namespace networkbearerselection {
 
 namespace {
-// The privileges that required in NetworkBearerSelection API
-const std::string kPrivilegeNetworkBearerSelection = "http://tizen.org/privilege/networkbearerselection";
+
+const std::string kPrivilegeNBS = "http://tizen.org/privilege/networkbearerselection";
 const std::string kPrivilegeInternet = "http://tizen.org/privilege/internet";
-const std::vector<std::string> kNbsPrivileges{kPrivilegeNetworkBearerSelection, kPrivilegeInternet};
+const std::vector<std::string> kNbsPrivileges{kPrivilegeNBS, kPrivilegeInternet};
 
-}  // namespace
+const std::string kNBSCallback = "NetworkBearerSelectionCallback_";
+} // namespace
 
 using namespace common;
 using namespace extension::networkbearerselection;
 
 NetworkBearerSelectionInstance::NetworkBearerSelectionInstance() {
-  LoggerD("Enter");
+  LoggerD("Entered");
   using std::placeholders::_1;
   using std::placeholders::_2;
 
@@ -60,7 +62,7 @@ NetworkBearerSelectionInstance::NetworkBearerSelectionInstance() {
 }
 
 NetworkBearerSelectionInstance::~NetworkBearerSelectionInstance() {
-  LoggerD("Enter");
+  LoggerD("Entered");
   NetworkBearerSelectionManager::GetInstance()->RemoveListener(this);
 }
 
@@ -71,9 +73,8 @@ NetworkBearerSelectionInstance::~NetworkBearerSelectionInstance() {
   }
 
 void NetworkBearerSelectionInstance::NetworkBearerSelectionRequestRouteToHost(
-    const picojson::value& args,
-    picojson::object& out) {
-  LoggerD("enter");
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
 
   CHECK_PRIVILEGE_ACCESS(kNbsPrivileges, &out);
 
@@ -81,122 +82,116 @@ void NetworkBearerSelectionInstance::NetworkBearerSelectionRequestRouteToHost(
   CHECK_EXIST(args, "id", out)
 
   const auto status = NetworkBearerSelectionManager::GetInstance()->getCellularState();
-
   if (!status) {
     LogAndReportError(status, &out, ("Failed to request route to host"));
     return;
   }
 
-  const std::string& domainName = args.get("domainName").get<std::string>();
-  const int listenerId = static_cast<int>(args.get("id").get<double>());
+  const std::string& domain_name = args.get("domainName").get<std::string>();
+  const int id = static_cast<int>(args.get("id").get<double>());
 
-  auto get = [=]()->void {
-    NetworkBearerSelectionManager::GetInstance()->requestRouteToHost(
-        domainName);
-  };
+  auto request = [=]()->void {
+    auto response = [this, domain_name, id](const common::PlatformResult result) -> void {
+      LoggerD("Entered");
+
+      picojson::value value {picojson::object{}};
+      picojson::object& obj = value.get<picojson::object>();
+
+      obj["id"] = picojson::value(static_cast<double>(id));
+      obj["listenerId"] = picojson::value(kNBSCallback + std::to_string(id));
 
-  listenerMap.insert(std::make_pair(domainName, listenerId));
+      if (result.IsSuccess()) {
+        ReportSuccess(obj);
+        this->addDomainListener(domain_name, id);
+      } else {
+        LogAndReportError(result, &obj);
+      }
 
-  common::TaskQueue::GetInstance().Async(get);
+      Instance::PostMessage(this, value.serialize().c_str());
+    };
+
+    NetworkBearerSelectionManager::GetInstance()->requestRouteToHost(domain_name, response);
+
+  };
+  common::TaskQueue::GetInstance().Async(request);
   ReportSuccess(out);
 }
 
 void NetworkBearerSelectionInstance::NetworkBearerSelectionReleaseRouteToHost(
-    const picojson::value& args,
-    picojson::object& out) {
-  LoggerD("enter");
+    const picojson::value& args, picojson::object& out) {
+  LoggerD("Entered");
 
   CHECK_PRIVILEGE_ACCESS(kNbsPrivileges, &out);
 
   CHECK_EXIST(args, "callbackId", out)
   CHECK_EXIST(args, "domainName", out)
-  const double callback_id = args.get("callbackId").get<double>();
-  const std::string& domainName = args.get("domainName").get<std::string>();
-
-  auto get = [ this, callback_id ](bool status)->void {
-    LoggerD("enter");
-    picojson::value response = picojson::value(picojson::object());
-    picojson::object& obj = response.get<picojson::object>();
-    if (status) {
-      ReportSuccess(obj);
-    } else {
-      LogAndReportError(UnknownException("PLATFORM ERROR"), obj, ("Failed to release route to host (callback)"));
-    }
-    obj["callbackId"] = picojson::value(callback_id);
-    Instance::PostMessage(this, response.serialize().c_str());
-  };
 
-  auto reply = [=](bool status)->void {
-    LoggerD("enter");
-    common::TaskQueue::GetInstance().Async(std::bind(get, status));
-  };
+  const double id = args.get("callbackId").get<double>();
+  const std::string& domain_name = args.get("domainName").get<std::string>();
 
-  const auto status = NetworkBearerSelectionManager::GetInstance()
-                                        ->releaseRouteToHost(domainName, reply);
-  if (status) {
-    ReportSuccess(out);
-  } else {
-    LogAndReportError(status, &out, ("Failed to release route to host"));
+  {
+    std::lock_guard<std::mutex> lock(m_listener_mutex_);
+    if (listenerMap.end() == listenerMap.find(domain_name)) {
+      LogAndReportError(UnknownException("Invalid argument"), out);
+      return;
+    }
   }
+
+  auto release = [=]()->void {
+    auto response = [this, domain_name, id](const common::PlatformResult result) -> void {
+      LoggerD("Entered");
+
+      picojson::value value {picojson::object{}};
+      picojson::object& obj = value.get<picojson::object>();
+
+      obj["callbackId"] = picojson::value(id);
+
+      if (result.IsSuccess()) {
+        ReportSuccess(obj);
+        this->removeDomainListener(domain_name);
+      } else {
+        LogAndReportError(result, &obj);
+      }
+
+      Instance::PostMessage(this, value.serialize().c_str());
+    };
+
+    NetworkBearerSelectionManager::GetInstance()->releaseRouteToHost(domain_name, response);
+  };
+  common::TaskQueue::GetInstance().Async(release);
+  ReportSuccess(out);
 }
 
-void NetworkBearerSelectionInstance::onNBSSuccess(
-    const std::string& domain_name) {
-  LoggerD("enter");
+void NetworkBearerSelectionInstance::onNBSEvent(const std::string& status) {
+  LoggerD("Entered");
+
   picojson::value event = picojson::value(picojson::object());
   picojson::object& obj = event.get<picojson::object>();
-  obj["domainName"] = picojson::value(domain_name);
-  obj["state"] = picojson::value("Success");
-
-  auto iterRange = listenerMap.equal_range(domain_name);
-  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
-    auto listenerId = (*iter).second;
-    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
-                                        std::to_string(listenerId));
-    obj["id"] = picojson::value(static_cast<double>(listenerId));
+
+  obj["status"] = picojson::value(status);
+  std::lock_guard<std::mutex> lock(m_listener_mutex_);
+  for (auto iter = listenerMap.begin(); iter != listenerMap.end(); ++iter) {
+    auto listener_id = (*iter).second;
+    obj["listenerId"] = picojson::value(kNBSCallback + std::to_string(listener_id));
+    obj["id"] = picojson::value(static_cast<double>(listener_id));
+
     LoggerD("Posting: %s", event.serialize().c_str());
     Instance::PostMessage(this, event.serialize().c_str());
   }
 }
 
-void NetworkBearerSelectionInstance::onNBSError(const std::string& domain_name,
-                                                const std::string& info) {
-  LoggerD("enter");
-  picojson::value event = picojson::value(picojson::object());
-  picojson::object& obj = event.get<picojson::object>();
-  LogAndReportError(UnknownException(info), obj);
-  obj["domainName"] = picojson::value(domain_name);
-  obj["state"] = picojson::value("Error");
-
-  auto iterRange = listenerMap.equal_range(domain_name);
-  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
-    auto listenerId = (*iter).second;
-    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
-                                        std::to_string(listenerId));
-    obj["id"] = picojson::value(static_cast<double>(listenerId));
-    LoggerD("Posting: %s", event.serialize().c_str());
-    Instance::PostMessage(this, event.serialize().c_str());
-  }
-  listenerMap.erase(domain_name);
+void NetworkBearerSelectionInstance::addDomainListener(
+    const std::string& domain_name, int listener_id) {
+  LoggerD("Entered");
+
+  std::lock_guard<std::mutex> lock(m_listener_mutex_);
+  listenerMap.insert(std::make_pair(domain_name, listener_id));
 }
 
-void NetworkBearerSelectionInstance::onNBSDisconnect(
-    const std::string& domain_name) {
-  LoggerD("enter");
-  picojson::value event = picojson::value(picojson::object());
-  picojson::object& obj = event.get<picojson::object>();
-  obj["domainName"] = picojson::value(domain_name);
-  obj["state"] = picojson::value("Disconnected");
-
-  auto iterRange = listenerMap.equal_range(domain_name);
-  for (auto iter = iterRange.first; iter != iterRange.second; ++iter) {
-    auto listenerId = (*iter).second;
-    obj["listenerId"] = picojson::value("NetworkBearerSelectionCallback_" +
-                                        std::to_string(listenerId));
-    obj["id"] = picojson::value(static_cast<double>(listenerId));
-    LoggerD("Posting: %s", event.serialize().c_str());
-    Instance::PostMessage(this, event.serialize().c_str());
-  }
+void NetworkBearerSelectionInstance::removeDomainListener(const std::string& domain_name) {
+  LoggerD("Entered");
+
+  std::lock_guard<std::mutex> lock(m_listener_mutex_);
   listenerMap.erase(domain_name);
 }
 
index d07d49c..7bc1d82 100644 (file)
 #define NETWORKBEARERSELECTION_NETWORKBEARERSELECTION_INSTANCE_H_
 
 #include "common/extension.h"
-#include "networkbearerselection_manager.h"
 #include <map>
+#include <mutex>
 
 namespace extension {
 namespace networkbearerselection {
 
-class NetworkBearerSelectionInstance : public common::ParsedInstance,
-                                       public NetworkBearerSelectionListener {
+class NetworkBearerSelectionInstance : public common::ParsedInstance {
  public:
   NetworkBearerSelectionInstance();
   virtual ~NetworkBearerSelectionInstance();
 
+  void onNBSEvent(const std::string& status);
  private:
-  void NetworkBearerSelectionRequestRouteToHost(const picojson::value& args,
-                                                picojson::object& out);
-  void NetworkBearerSelectionReleaseRouteToHost(const picojson::value& args,
-                                                picojson::object& out);
+  void NetworkBearerSelectionRequestRouteToHost(const picojson::value& args, picojson::object& out);
+  void NetworkBearerSelectionReleaseRouteToHost(const picojson::value& args, picojson::object& out);
 
-  virtual void onNBSSuccess(const std::string& domain_name);
-  virtual void onNBSError(const std::string& domain_name,
-                          const std::string& info);
-  virtual void onNBSDisconnect(const std::string& domain_name);
+  void addDomainListener(const std::string& domain_name, int listener_id);
+  void removeDomainListener(const std::string& domain_name);
 
   std::multimap<std::string, int> listenerMap;
+  std::mutex m_listener_mutex_;
 };
 
 }  // namespace networkbearerselection
index 4c3ff43..f777326 100644 (file)
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <memory>
+#include <thread>
 
 namespace extension {
 namespace networkbearerselection {
 
+using namespace common;
+
 namespace {
-const char* kPlatformError = "Platform error";
+const char* kEventSuccess = "success";
+const char* kEventDisconnected = "disconnected";
 }
 
-struct NetworkBearerSelectionRequestEvent {
+struct NetworkBearerSelectionEvent {
   std::string domain_name;
-  NetworkBearerSelectionRequestEvent(const std::string& dm) : domain_name(dm) {}
-};
+  ReplyCallback callback;
 
-struct NetworkBearerSelectionReleaseEvent {
-  std::string domain_name;
-  NetworkBearerSelectionManager::ReleaseReplyCallback callback;
-  NetworkBearerSelectionReleaseEvent(
-      const std::string& dm,
-      const NetworkBearerSelectionManager::ReleaseReplyCallback& cb)
-      : domain_name(dm), callback(cb) {}
+  NetworkBearerSelectionEvent(const std::string& dm, const ReplyCallback& cb):
+    domain_name(dm),
+    callback(cb) {
+  }
 };
 
-void NetworkBearerSelectionManager::AddListener(
-    NetworkBearerSelectionListener* listener) {
-  LoggerD("Enter");
+void NetworkBearerSelectionManager::AddListener(NetworkBearerSelectionInstance* listener) {
+  LoggerD("Entered");
+
   std::lock_guard<std::mutex> lock(m_mutex_);
   m_listeners_.push_back(listener);
 }
 
-void NetworkBearerSelectionManager::RemoveListener(
-    NetworkBearerSelectionListener* listener) {
-  LoggerD("Enter");
+void NetworkBearerSelectionManager::RemoveListener(NetworkBearerSelectionInstance* listener) {
+  LoggerD("Entered");
+
   std::lock_guard<std::mutex> lock(m_mutex_);
   m_listeners_.remove(listener);
 }
 
 NetworkBearerSelectionManager* NetworkBearerSelectionManager::GetInstance() {
-  LoggerD("Enter");
+  LoggerD("Entered");
+
   static NetworkBearerSelectionManager instance;
   return &instance;
 }
@@ -66,11 +67,11 @@ NetworkBearerSelectionManager* NetworkBearerSelectionManager::GetInstance() {
 NetworkBearerSelectionManager::NetworkBearerSelectionManager()
     : m_connection_handle_(nullptr),
       m_profile_handle_(nullptr),
-      m_connection_state_(ConnectionState::Unknown),
-      m_is_connection_open_(false) {
-  LoggerD("Enter");
-  int ret = connection_create(&m_connection_handle_);
+      m_profile_name_(),
+      m_is_connection_opened_(false) {
+  LoggerD("Entered");
 
+  int ret = connection_create(&m_connection_handle_);
   if (CONNECTION_ERROR_NONE == ret) {
     LoggerD("Client registration success");
   } else {
@@ -80,482 +81,458 @@ NetworkBearerSelectionManager::NetworkBearerSelectionManager()
 }
 
 NetworkBearerSelectionManager::~NetworkBearerSelectionManager() {
-  LoggerD("Enter");
-  if (m_connection_handle_ != nullptr) {
-    LoggerD("Client deregistration success");
-    destroyProfileHandle();
-    connection_destroy(m_connection_handle_);
-  } else {
-    LoggerE("Client deregistration failed");
-  }
+  LoggerD("Entered");
 
-  {
-    std::lock_guard<std::mutex> lock(m_request_mutex_);
-    LoggerD("Delete %d request object(s)", m_request_events_.size());
-    m_request_events_.clear();
+  for (auto it = m_domain_names_.begin(); it != m_domain_names_.end(); ++it) {
+    if (!removeDomainRoute(it)) {
+      LoggerE("Failed to remove route [%s]", it->first.c_str());
+    }
   }
 
-  {
-    std::lock_guard<std::mutex> lock(m_release_mutex_);
-    LoggerD("Delete %d release object(s)", m_release_events_.size());
-    m_release_events_.clear();
+  if (nullptr != m_connection_handle_) {
+    destroyProfileHandler();
+    if (CONNECTION_ERROR_NONE != connection_destroy(m_connection_handle_)) {
+      LoggerE("Failed to destroy connection");
+    }
   }
 }
 
 void NetworkBearerSelectionManager::connection_state_changed_callback(
-    connection_profile_state_e state,
-    void* user_data) {
-  LoggerD("enter");
-  if (user_data != nullptr) {
-    LoggerD("Callback registration Succeeded");
-    if (state == CONNECTION_PROFILE_STATE_ASSOCIATION) {
-      LoggerD("association state");
-      return;
-    }
+    connection_profile_state_e state, void* user_data) {
+  LoggerD("Entered [%d]", state);
 
-    RequestEventPtr event = NetworkBearerSelectionManager::GetInstance()->getRequestEvent(
-        static_cast<NetworkBearerSelectionRequestEvent*>(user_data));
-    if (!event) {
-      LoggerD("Event is not found.");
-      return;
-    }
-
-    if (state == CONNECTION_PROFILE_STATE_DISCONNECTED) {
-      std::string domain_name = event->domain_name;
-      NetworkBearerSelectionManager::GetInstance()->deregistStateChangeListener(domain_name);
-
-      NetworkBearerSelectionManager::GetInstance()->makeDisconnectCallback(domain_name);
-    }
+  if (CONNECTION_PROFILE_STATE_CONNECTED == state) {
+    NetworkBearerSelectionManager::GetInstance()->makeSuccessCallback();
+  } else if (CONNECTION_PROFILE_STATE_DISCONNECTED == state) {
+    NetworkBearerSelectionManager::GetInstance()->makeDisconnectCallback();
   }
 }
 
-void NetworkBearerSelectionManager::connection_profile_opened_callback(
-    connection_error_e result,
-    void* user_data) {
-  LoggerD("enter");
-  if (user_data == nullptr) {
-    LoggerD("Error: null passed in profile open callback");
+void NetworkBearerSelectionManager::connection_opened_callback(
+    connection_error_e result, void* user_data) {
+  LoggerD("Entered");
+
+  if (nullptr == user_data) {
+    LoggerD("User data not found");
     return;
   }
 
-  RequestEventPtr event = NetworkBearerSelectionManager::GetInstance()->getRequestEvent(
-      static_cast<NetworkBearerSelectionRequestEvent*>(user_data));
+  NetworkBearerSelectionEvent* event = static_cast<NetworkBearerSelectionEvent*>(user_data);
   if (!event) {
-    LoggerD("Event is not found.");
+    LoggerE("Event not found");
     return;
   }
 
   std::string domain_name = event->domain_name;
-
-  if (result == CONNECTION_ERROR_NONE) {
-    LoggerD("Connection open Succeeded");
-    if (user_data != nullptr) {
-      NetworkBearerSelectionManager::GetInstance()->registStateChangeListener(
-          domain_name);
+  ReplyCallback callback = event->callback;
+  NetworkBearerSelectionManager* manager = NetworkBearerSelectionManager::GetInstance();
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR, "Connection opened");
+
+  LoggerD("Domain name %s", domain_name.c_str());
+  if (CONNECTION_ERROR_NONE == result) {
+    if (!manager->registerStateChangeListener(domain_name)) {
+      LoggerE("Failed to open connection");
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to open connection");
     }
-  } else {
-    LoggerD("Connection open Failed");
-    NetworkBearerSelectionManager::GetInstance()->makeErrorCallback(
-        domain_name, kPlatformError);
   }
+
+  manager->callResultCallback(callback, ret);
+  delete event;
 }
 
 void NetworkBearerSelectionManager::connection_closed_callback(
-    connection_error_e result,
-    void* user_data) {
-  LoggerD("enter");
-  if (user_data == nullptr) {
-    LoggerD("Error: null passed in profile open callback");
+    connection_error_e result, void* user_data) {
+  LoggerD("Entered");
+
+  if (nullptr == user_data) {
+    LoggerD("User data not found");
     return;
   }
 
-  ReleaseEventPtr event = NetworkBearerSelectionManager::GetInstance()->getReleaseEvent(
-      static_cast<NetworkBearerSelectionReleaseEvent*>(user_data));
+  NetworkBearerSelectionEvent* event = static_cast<NetworkBearerSelectionEvent*>(user_data);
   if (!event) {
-    LoggerD("Event is not found.");
+    LoggerE("Event not found");
     return;
   }
 
   std::string domain_name = event->domain_name;
-  ReleaseReplyCallback callback = event->callback;
-
-  if (result == CONNECTION_ERROR_NONE) {
-    LoggerD("Connection close Succeeded");
-    if (user_data != nullptr) {
-      NetworkBearerSelectionManager::GetInstance()->deregistStateChangeListener(
-          domain_name);
-      callback(true);
+  ReplyCallback callback = event->callback;
+  NetworkBearerSelectionManager* manager = NetworkBearerSelectionManager::GetInstance();
+  PlatformResult ret = PlatformResult(ErrorCode::NO_ERROR, "Connection closed");
+
+  LoggerD("Domain name %s", domain_name.c_str());
+  if (CONNECTION_ERROR_NONE == result) {
+    if (!manager->deregisterStateChangeListener(domain_name)) {
+      LoggerE("Failed to close connection");
+      ret = PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to close connection");
     }
-  } else {
-    callback(false);
   }
+
+  manager->callResultCallback(callback, ret);
+  delete event;
 }
 
-common::PlatformResult NetworkBearerSelectionManager::getCellularState() {
+PlatformResult NetworkBearerSelectionManager::getCellularState() {
+  LoggerD("Entered");
 
   connection_cellular_state_e state;
 
   int ret = connection_get_cellular_state(m_connection_handle_, &state);
-
-  if (ret != CONNECTION_ERROR_NONE) {
+  if (CONNECTION_ERROR_NONE != ret) {
     LoggerE("Fail to get connection state. %d", ret);
-    return common::PlatformResult(GetNBSErrorCode(ret),
-                                  "Fail to get connection state.");
+    return PlatformResult(GetNBSErrorCode(ret), "Failed to get connection state");
   }
 
-  if (state == CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE) {
+  if (CONNECTION_CELLULAR_STATE_OUT_OF_SERVICE == state) {
     LoggerE("Network cellular have no service. %d", state);
-    return common::PlatformResult(common::ErrorCode::NOT_SUPPORTED_ERR,
-                                  "Network cellular have no service. emulator doesn't support the API.");
+    return PlatformResult(ErrorCode::NOT_SUPPORTED_ERR, "Network cellular have no service");
   }
-  return common::PlatformResult(common::ErrorCode::NO_ERROR);
+
+  return PlatformResult(ErrorCode::NO_ERROR);
 }
 
+void NetworkBearerSelectionManager::callResultCallback(
+    const ReplyCallback& reply, const PlatformResult result) {
+  LoggerD("Entered");
+
+  std::thread(reply, result).detach();
+}
 
 void NetworkBearerSelectionManager::requestRouteToHost(
-    const std::string& domain_name) {
-  LoggerD("NetworkBearerSelectionManager::requestRouteToHost");
-  connection_profile_h profileHandle;
+    const std::string& domain_name, const ReplyCallback& reply) {
+  LoggerD("Entered");
 
-  if (m_connection_state_ == ConnectionState::Connected) {
+  connection_profile_h profile_h = nullptr;
+  char* current_profile_name_c = nullptr;
+
+  SCOPE_EXIT {
+    if (profile_h) {
+      connection_profile_destroy(profile_h);
+    }
+    free(current_profile_name_c);
+  };
+
+  if (m_is_connection_opened_) {
     LoggerD("connection is already opened.");
-    for (std::list<std::string>::iterator it = m_domain_names_.begin();
-         it != m_domain_names_.end();
-         it++) {
-      if (*it == domain_name) {
-        LoggerD("Same domain name is exist in list.");
-        makeSuccessCallback(domain_name);
-        return;
-      }
+    auto it = m_domain_names_.find(domain_name);
+    if (m_domain_names_.end() != it) {
+      callResultCallback(reply, PlatformResult(ErrorCode::NO_ERROR, "Domain already requested"));
+      return;
     }
   }
 
-  destroyProfileHandle();
-
-  int ret = connection_get_default_cellular_service_profile(
-      m_connection_handle_,
-      CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET,
-      &m_profile_handle_);
-
-  if (ret != CONNECTION_ERROR_NONE) {
-    LoggerE("Fail to get profile handle. %d", ret);
-    makeErrorCallback(domain_name, kPlatformError);
+  if (!createProfileHandler()) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get cellular profile"));
     return;
   }
 
-  char* defaultProfileName_c = nullptr;
-  std::string defaultProfileName;
-
-  connection_profile_get_name(m_profile_handle_, &defaultProfileName_c);
-  if (defaultProfileName_c == nullptr) {
-    LoggerE("default profile is not exist.");
-    makeErrorCallback(domain_name, kPlatformError);
+  int ret = connection_get_current_profile(m_connection_handle_, &profile_h);
+  if (CONNECTION_ERROR_NONE != ret) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get current profile"));
     return;
   }
-  defaultProfileName = defaultProfileName_c;
-  free(defaultProfileName_c);
-  defaultProfileName_c = nullptr;
 
-  if (connection_get_current_profile(m_connection_handle_, &profileHandle) !=
-      CONNECTION_ERROR_NONE) {
-    LoggerE("Fail to get current profile handle");
-    makeErrorCallback(domain_name, kPlatformError);
+  std::string current_profile_name;
+  ret = connection_profile_get_name(profile_h, &current_profile_name_c);
+  if (CONNECTION_ERROR_NONE != ret || nullptr == current_profile_name_c) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get profile name"));
     return;
   }
 
-  char* currentProfileName_c = nullptr;
-  std::string currentProfileName;
-  if (connection_profile_get_name(profileHandle, &currentProfileName_c) !=
-      CONNECTION_ERROR_NONE) {
-    LoggerE("Fail to get current profile name");
-    if (currentProfileName_c != nullptr) {
-      free(currentProfileName_c);
-      currentProfileName_c = nullptr;
+  current_profile_name = current_profile_name_c;
+
+  LoggerD("defaultProfileName [%s]", m_profile_name_.c_str());
+  LoggerD("currentProfileName [%s]", current_profile_name.c_str());
+  if (!m_is_connection_opened_ || m_profile_name_ != current_profile_name) {
+    LoggerD("Open profile");
+
+    NetworkBearerSelectionEvent* event(new NetworkBearerSelectionEvent(domain_name, reply));
+    ret = connection_open_profile(m_connection_handle_, m_profile_handle_,
+                                  connection_opened_callback, event);
+    if (CONNECTION_ERROR_NONE != ret) {
+      delete event;
+      callResultCallback(reply,
+                         LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to open profile"));
     }
-    makeErrorCallback(domain_name, kPlatformError);
+
     return;
   }
 
-  if (currentProfileName_c == nullptr) {
-    LoggerE("current profile is not exist.");
-    makeErrorCallback(domain_name, kPlatformError);
-    return;
+  bool result = registerStateChangeListener(domain_name);
+  if (result) {
+    callResultCallback(reply, PlatformResult(ErrorCode::NO_ERROR, "Domain request success"));
+  } else {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to register listener"));
   }
-  currentProfileName = currentProfileName_c;
-  free(currentProfileName_c);
-  currentProfileName_c = nullptr;
+}
+
+bool NetworkBearerSelectionManager::removeDomainRoute(
+    const std::map<std::string, int>::iterator& iter) {
+  LoggerD("Entered");
+
+  const char* domain_name = iter->first.c_str();
+  char* interface_name = nullptr;
+  char* gateway = nullptr;
 
-  if (defaultProfileName != currentProfileName) {
-    RequestEventPtr event(new NetworkBearerSelectionRequestEvent(domain_name));
+  SCOPE_EXIT {
+    free(interface_name);
+    free(gateway);
+  };
+
+  int ret = connection_profile_get_network_interface_name(m_profile_handle_, &interface_name);
+  if (CONNECTION_ERROR_NONE != ret) {
+    LoggerE("Failed to get interface name");
+    return false;
+  }
 
-    if (connection_open_profile(m_connection_handle_,
-                                m_profile_handle_,
-                                connection_profile_opened_callback,
-                                event.get()) != CONNECTION_ERROR_NONE) {
-      LoggerE("Connection open Failed");
-      makeErrorCallback(domain_name, kPlatformError);
-    } else {
-      m_is_connection_open_ = true;
+  int ai_family = iter->second;
+  if (AF_INET == ai_family) {
+    LoggerD("IPv4 address");
+    ret = connection_remove_route(m_connection_handle_, interface_name, domain_name);
+  } else if (AF_INET6 == ai_family) {
+    LoggerD("IPv6 address");
+    ret = connection_profile_get_gateway_address(
+        m_profile_handle_, CONNECTION_ADDRESS_FAMILY_IPV6, &gateway);
 
-      std::lock_guard<std::mutex> lock(m_request_mutex_);
-      m_request_events_.push_back(event);
+    if (CONNECTION_ERROR_NONE != ret) {
+      LoggerE("Failed to get gateway");
+      return false;
     }
+
+    ret = connection_remove_route_ipv6(
+        m_connection_handle_, interface_name, domain_name, gateway);
   } else {
-    registStateChangeListener(domain_name);
+    LoggerE("Incorrect family address");
+    return false;
+  }
+
+  if (CONNECTION_ERROR_NONE != ret) {
+    LoggerE("Failed to remove route");
+    return false;
   }
+
+  return true;
 }
 
-common::PlatformResult NetworkBearerSelectionManager::releaseRouteToHost(
-    const std::string& domain_name, const ReleaseReplyCallback& reply_cb) {
-  LoggerD("enter");
-
-  for (const auto& name : m_domain_names_) {
-    if (name == domain_name) {
-      LoggerD("Same domain name is exist in list.");
-      m_domain_names_.remove(domain_name);
-      LoggerD("list size : %i", m_domain_names_.size());
-      if (m_domain_names_.size() == 0) {
-        if (!m_profile_handle_) {
-          return LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "Already in use");
-        }
-
-        if (connection_profile_unset_state_changed_cb(m_profile_handle_) !=
-            CONNECTION_ERROR_NONE) {
-          LoggerE("unset callback is failed");
-          destroyProfileHandle();
-          return common::PlatformResult(common::ErrorCode::NO_ERROR);
-        }
-
-        if (m_is_connection_open_) {
-          ReleaseEventPtr event(new NetworkBearerSelectionReleaseEvent(domain_name, reply_cb));
-
-          if (connection_close_profile(m_connection_handle_,
-                                       m_profile_handle_,
-                                       connection_closed_callback,
-                                       event.get()) != CONNECTION_ERROR_NONE) {
-            LoggerE("connection close failed");
-            reply_cb(false);
-          } else {
-            m_is_connection_open_ = false;
-            deregistStateChangeListener(domain_name);
-
-            std::lock_guard<std::mutex> lock(m_release_mutex_);
-            m_release_events_.push_back(event);
-          }
-        } else {
-          reply_cb(true);
-        }
-      }
-      return common::PlatformResult(common::ErrorCode::NO_ERROR);
-    }
+void NetworkBearerSelectionManager::releaseRouteToHost(
+    const std::string& domain_name, const ReplyCallback& reply) {
+  LoggerD("Entered");
+
+  if (!m_profile_handle_) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Profile handle not found"));
+    return;
+  }
+
+  auto iter = m_domain_names_.find(domain_name);
+  if (m_domain_names_.end() == iter) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Domain not found"));
+    return;
+  }
+
+  if (!removeDomainRoute(iter)) {
+    callResultCallback(reply,
+                       LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to remove route"));
+    return;
+  }
+
+  m_domain_names_.erase(iter);
+  if (m_domain_names_.size()) {
+    callResultCallback(reply, PlatformResult(ErrorCode::NO_ERROR, "Domain route released"));
+    return;
   }
 
-  return LogAndCreateResult(common::ErrorCode::UNKNOWN_ERR, "Invalid argument");
+  if (m_is_connection_opened_) {
+    NetworkBearerSelectionEvent* event(new NetworkBearerSelectionEvent(domain_name, reply));
+    int ret = connection_close_profile(m_connection_handle_, m_profile_handle_,
+                                       connection_closed_callback, event);
+    if (CONNECTION_ERROR_NONE != ret) {
+      delete event;
+      callResultCallback(reply,
+                         LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to close connection"));
+      return;
+    }
+  }
 }
 
-void NetworkBearerSelectionManager::registStateChangeListener(
-    const std::string& domain_name) {
-  LoggerD("enter");
-  char* interfaceName = nullptr;
-  char* hostAddr = nullptr;
+bool NetworkBearerSelectionManager::registerStateChangeListener(const std::string& domain_name) {
+  LoggerD("Entered");
+
+  char* interface_name = nullptr;
   char* gateway = nullptr;
-  std::unique_ptr<char, void(*)(void*)> host_addr_ptr(nullptr, &std::free);
-  struct addrinfo* servinfo = nullptr;
+  struct addrinfo* serv_info = nullptr;
 
   SCOPE_EXIT {
-    if (interfaceName) {
-      free(interfaceName);
-    }
-    if (gateway) {
-      free(gateway);
-    }
-    freeaddrinfo(servinfo);
+    free(interface_name);
+    free(gateway);
+    freeaddrinfo(serv_info);
   };
 
-  if (connection_profile_get_network_interface_name(
-          m_profile_handle_, &interfaceName) != CONNECTION_ERROR_NONE) {
+  m_is_connection_opened_ = true;
+
+  int ret = connection_profile_get_network_interface_name(m_profile_handle_, &interface_name);
+  if (CONNECTION_ERROR_NONE != ret) {
     LoggerE("Fail to get interface name!");
-    destroyProfileHandle();
-    makeErrorCallback(domain_name, kPlatformError);
-  } else {
-    LoggerD("Interface name : %s", interfaceName);
+    return false;
   }
 
+  LoggerD("Interface name: %s", interface_name);
   LoggerD("Domain name to be resolved: %s", domain_name.c_str());
 
-  int ret_val = getaddrinfo(domain_name.c_str() , nullptr , nullptr , &servinfo);
-  if (0 != ret_val) {
-    LoggerE("Error while calling getaddrinfo(): %s", gai_strerror(ret_val));
-    destroyProfileHandle();
-    makeErrorCallback(domain_name, kPlatformError);
-    return;
+  ret = getaddrinfo(domain_name.c_str(), nullptr, nullptr, &serv_info);
+  if (0 != ret) {
+    LoggerE("Failed to get address info: %s", gai_strerror(ret));
+    return false;
+  }
+
+  struct in_addr *addr = nullptr;
+  if (AF_INET == serv_info->ai_family) {
+    LoggerD("IPv4 address");
+    struct sockaddr_in *ipv = (struct sockaddr_in *) serv_info->ai_addr;
+    addr = &(ipv->sin_addr);
+  } else if (AF_INET6 == serv_info->ai_family) {
+    LoggerD("IPv6 address");
+    struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *) serv_info->ai_addr;
+    addr = (struct in_addr*) &ipv6->sin6_addr;
   } else {
-    hostAddr = new char[servinfo->ai_addrlen + 1];
-    host_addr_ptr.reset(hostAddr);
-
-    struct in_addr  *addr = nullptr;
-    if (AF_INET == servinfo->ai_family) {
-      LoggerD("IPv4 address");
-      struct sockaddr_in *ipv = (struct sockaddr_in *)servinfo->ai_addr;
-      addr = &(ipv->sin_addr);
-    } else {
-      LoggerD("IPv6 address");
-      struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)servinfo->ai_addr;
-      addr = (struct in_addr *) &(ipv6->sin6_addr);
-    }
+    LoggerE("Unknown ai_family address");
+    return false;
+  }
 
-    if (nullptr == inet_ntop(servinfo->ai_family, addr, hostAddr, servinfo->ai_addrlen)) {
-      LoggerE("Error while calling inet_ntop()");
-      destroyProfileHandle();
-      makeErrorCallback(domain_name, kPlatformError);
-      return;
-    }
-    LoggerD("hostAddr : %s", hostAddr);
+  std::unique_ptr<char, void(*)(void*)> host_addr_ptr(new char[serv_info->ai_addrlen + 1], &std::free);
+
+  if (nullptr == inet_ntop(serv_info->ai_family, addr, host_addr_ptr.get(), serv_info->ai_addrlen)) {
+    LoggerE("Failed to convert address");
+    return false;
   }
 
-  RequestEventPtr event(new NetworkBearerSelectionRequestEvent(domain_name));
+  LoggerD("hostAddr: %s", host_addr_ptr.get());
 
-  if (connection_profile_set_state_changed_cb(m_profile_handle_,
-                                              connection_state_changed_callback,
-                                              event.get()) != CONNECTION_ERROR_NONE) {
+  ret = connection_profile_set_state_changed_cb(
+      m_profile_handle_, connection_state_changed_callback, nullptr);
+  if (CONNECTION_ERROR_NONE != ret ) {
     LoggerE("Callback register is failed.");
-    destroyProfileHandle();
+    return false;
+  }
+
+  if (AF_INET == serv_info->ai_family) {
+    LoggerD("IPv4 add route");
+    ret = connection_add_route(m_connection_handle_, interface_name, host_addr_ptr.get());
   } else {
-    int ret = CONNECTION_ERROR_NONE;
-    if (AF_INET == servinfo->ai_family) {
-      LoggerD("IPv4 add route");
-      ret = connection_add_route(m_connection_handle_, interfaceName, hostAddr);
-    } else if (AF_INET6 == servinfo->ai_family) {
-      LoggerD("IPv6 add route");
-      ret = connection_profile_get_gateway_address(
-          m_profile_handle_, CONNECTION_ADDRESS_FAMILY_IPV6, &gateway);
-
-      if (CONNECTION_ERROR_NONE != ret) {
-        LoggerD("Error %d", ret);
-        makeErrorCallback(domain_name, kPlatformError);
-        return;
-      }
-
-      ret = connection_add_route_ipv6(m_connection_handle_, interfaceName, hostAddr, gateway);
-    } else {
-      LoggerE("Unknown ai_family address");
-      makeErrorCallback(domain_name, kPlatformError);
-      return;
-    }
+    LoggerD("IPv6 add route");
+    ret = connection_profile_get_gateway_address(m_profile_handle_, CONNECTION_ADDRESS_FAMILY_IPV6, &gateway);
 
     if (CONNECTION_ERROR_NONE != ret) {
-      LoggerE("add route is failed.");
-      connection_profile_unset_state_changed_cb(m_profile_handle_);
-      makeErrorCallback(domain_name, kPlatformError);
-    } else {
-      LoggerD("add route is successed.");
-      m_domain_names_.push_back(domain_name);
-      makeSuccessCallback(domain_name);
+      LoggerE("Error while getting gateway address %d", ret);
+      return false;
     }
 
-    std::lock_guard<std::mutex> lock(m_request_mutex_);
-    m_request_events_.push_back(event);
+    ret = connection_add_route_ipv6(m_connection_handle_, interface_name, host_addr_ptr.get(), gateway);
+  }
+
+  if (CONNECTION_ERROR_NONE != ret) {
+    LoggerE("Adding route failed");
+    return false;
+  } else {
+    LoggerD("Adding route success");
+    std::lock_guard<std::mutex> lock(m_mutex_);
+    m_domain_names_[domain_name] = serv_info->ai_family;
+    return true;
   }
 }
 
-void NetworkBearerSelectionManager::deregistStateChangeListener(
-    const std::string& domain_name) {
-  LoggerD("enter");
+bool NetworkBearerSelectionManager::deregisterStateChangeListener(const std::string& domain_name) {
+  LoggerD("Entered");
+
   if (m_profile_handle_) {
-    connection_profile_unset_state_changed_cb(m_profile_handle_);
-    connection_profile_destroy(m_profile_handle_);
-    m_profile_handle_ = nullptr;
+    int ret = connection_profile_unset_state_changed_cb(m_profile_handle_);
+    if (CONNECTION_ERROR_NONE != ret) {
+      LoggerE("Failed to unset state callback");
+      return false;
+    }
   }
-  m_domain_names_.remove(domain_name);
-  m_connection_state_ = ConnectionState::Disconnected;
-}
 
-void NetworkBearerSelectionManager::makeSuccessCallback(
-    const std::string& domain_name) {
-  LoggerD("enter");
-  std::lock_guard<std::mutex> lock(m_mutex_);
-  for (NetworkBearerSelectionListener* listener : m_listeners_)
-    listener->onNBSSuccess(domain_name);
+  m_is_connection_opened_ = false;
+  return true;
 }
 
-void NetworkBearerSelectionManager::makeErrorCallback(
-    const std::string& domain_name,
-    const char* info) {
-  LoggerD("enter");
-  std::string l_info = info;
-  makeErrorCallback(domain_name, l_info);
-}
+void NetworkBearerSelectionManager::makeSuccessCallback() {
+  LoggerD("Entered");
 
-void NetworkBearerSelectionManager::makeErrorCallback(
-    const std::string& domain_name,
-    const std::string& info) {
-  LoggerD("enter");
   std::lock_guard<std::mutex> lock(m_mutex_);
-  for (NetworkBearerSelectionListener* listener : m_listeners_)
-    listener->onNBSError(domain_name, info);
+  for (NetworkBearerSelectionInstance* listener : m_listeners_) {
+    listener->onNBSEvent(kEventSuccess);
+  }
 }
 
-void NetworkBearerSelectionManager::makeDisconnectCallback(
-    const std::string& domain_name) {
-  LoggerD("enter");
+void NetworkBearerSelectionManager::makeDisconnectCallback() {
+  LoggerD("Entered");
+
   std::lock_guard<std::mutex> lock(m_mutex_);
-  for (NetworkBearerSelectionListener* listener : m_listeners_)
-    listener->onNBSDisconnect(domain_name);
+  for (NetworkBearerSelectionInstance* listener : m_listeners_) {
+    listener->onNBSEvent(kEventDisconnected);
+  }
 }
 
-void NetworkBearerSelectionManager::destroyProfileHandle() {
-  LoggerD("enter");
+void NetworkBearerSelectionManager::destroyProfileHandler() {
+  LoggerD("Entered");
+
   if (m_profile_handle_) {
-    connection_profile_destroy(m_profile_handle_);
-    m_profile_handle_ = nullptr;
+    if (CONNECTION_ERROR_NONE != connection_profile_destroy(m_profile_handle_)) {
+      LoggerE("Failed to destroy profile");
+    }
   }
 }
 
-RequestEventPtr NetworkBearerSelectionManager::getRequestEvent(NetworkBearerSelectionRequestEvent* event) {
-  LoggerD("enter");
-  std::lock_guard<std::mutex> lock(m_request_mutex_);
-  for (auto it = m_request_events_.begin(); it != m_request_events_.end(); it++) {
-    if (it->get() == event) {
-      LoggerD("Found object [%p]", it->get());
-      RequestEventPtr ev = *it;
-      m_request_events_.erase(it);
-      return ev;
-    }
+ErrorCode NetworkBearerSelectionManager::GetNBSErrorCode(int error_code) {
+  LoggerD("Entered");
+
+  switch (error_code) {
+    case CONNECTION_ERROR_NOT_SUPPORTED:
+      return ErrorCode::NOT_SUPPORTED_ERR;
+    default:
+      return ErrorCode::UNKNOWN_ERR;
   }
-  return nullptr;
 }
 
-ReleaseEventPtr NetworkBearerSelectionManager::getReleaseEvent(NetworkBearerSelectionReleaseEvent* event) {
-  LoggerD("enter");
-  std::lock_guard<std::mutex> lock(m_release_mutex_);
-  for (auto it = m_release_events_.begin(); it != m_release_events_.end(); it++) {
-    if (it->get() == event) {
-      LoggerD("Found object [%p]", it->get());
-      ReleaseEventPtr ev = *it;
-      m_release_events_.erase(it);
-      return ev;
-    }
+bool NetworkBearerSelectionManager::createProfileHandler() {
+ LoggerD("Entered");
+
+  if (!m_connection_handle_) {
+    LoggerE("Connection handle is not created");
+    return false;
   }
-  return nullptr;
-}
 
-common::ErrorCode NetworkBearerSelectionManager::GetNBSErrorCode(int error_code) {
+  int ret = CONNECTION_ERROR_NONE;
+  if (!m_profile_handle_) {
+    ret = connection_get_default_cellular_service_profile(
+        m_connection_handle_, CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET, &m_profile_handle_);
 
-  common::ErrorCode error = common::ErrorCode::UNKNOWN_ERR;
+    if (CONNECTION_ERROR_NONE != ret) {
+      LoggerE("Failed to get cellular profile");
+      m_profile_handle_ = nullptr;
+      return false;
+    }
+  }
 
-  switch (error_code) {
-    case CONNECTION_ERROR_OPERATION_FAILED:
-       error = common::ErrorCode::UNKNOWN_ERR;
-       break;
-    case CONNECTION_ERROR_NOT_SUPPORTED:
-       error = common::ErrorCode::NOT_SUPPORTED_ERR;
-       break;
-    default:
-      error = common::ErrorCode::UNKNOWN_ERR;
-      break;
+  if (m_profile_name_.empty()) {
+    char* profile_name = nullptr;
+    ret = connection_profile_get_name(m_profile_handle_, &profile_name);
+    if (CONNECTION_ERROR_NONE != ret || nullptr == profile_name) {
+      LoggerE("Failed to get cellular profile name");
+      return false;
+    }
+
+    m_profile_name_ = profile_name;
+    free(profile_name);
   }
 
-  return error;
+  return true;
 }
 
 }  // namespace networkbearerselection
index 7e45a58..3edad48 100644 (file)
@@ -19,7 +19,6 @@
 
 #include <string>
 #include <list>
-#include <vector>
 #include <mutex>
 #include <memory>
 #include <functional>
 #include <net_connection.h>
 
 #include "common/platform_result.h"
+#include "networkbearerselection_instance.h"
 
 namespace extension {
 namespace networkbearerselection {
 
-enum class ConnectionState {
-  Unknown,
-  Connected,
-  Disconnected,
-  ConnectionFailed
-};
-
-enum class NetworkType {
-  Cellular,
-  Unknown
-};
+struct NetworkBearerSelectionEvent;
 
-struct NetworkBearerSelectionRequestEvent;
-struct NetworkBearerSelectionReleaseEvent;
-
-typedef std::shared_ptr<NetworkBearerSelectionRequestEvent> RequestEventPtr;
-typedef std::shared_ptr<NetworkBearerSelectionReleaseEvent> ReleaseEventPtr;
-
-class NetworkBearerSelectionListener {
- public:
-  virtual void onNBSSuccess(const std::string& domain_name) = 0;
-  virtual void onNBSError(const std::string& domain_name,
-                          const std::string& info) = 0;
-  virtual void onNBSDisconnect(const std::string& domain_name) = 0;
-};
+typedef std::shared_ptr<NetworkBearerSelectionEvent> EventPtr;
+typedef std::function<void(const common::PlatformResult)> ReplyCallback;
 
 class NetworkBearerSelectionManager {
  public:
-  typedef std::function<void(bool)> ReleaseReplyCallback;
-  void AddListener(NetworkBearerSelectionListener* listener);
-  void RemoveListener(NetworkBearerSelectionListener* listener);
-
-  void requestRouteToHost(const std::string& domain_name);
-  common::PlatformResult releaseRouteToHost(const std::string& domain_name,
-                                            const ReleaseReplyCallback& reply_cb);
+  void AddListener(NetworkBearerSelectionInstance* listener);
+  void RemoveListener(NetworkBearerSelectionInstance* listener);
 
+  void callResultCallback(const ReplyCallback& reply, const common::PlatformResult result);
+  void requestRouteToHost(const std::string& domain_name, const ReplyCallback& reply);
+  void releaseRouteToHost(const std::string& domain_name, const ReplyCallback& reply);
   common::PlatformResult getCellularState();
-
   static NetworkBearerSelectionManager* GetInstance();
 
   NetworkBearerSelectionManager(const NetworkBearerSelectionManager&) = delete;
-  NetworkBearerSelectionManager& operator=(
-      const NetworkBearerSelectionManager&) = delete;
+  NetworkBearerSelectionManager& operator=(const NetworkBearerSelectionManager&) = delete;
 
  private:
-  static void connection_state_changed_callback(
-      connection_profile_state_e state,
-      void* user_data);
-  static void connection_profile_opened_callback(connection_error_e result,
-                                                 void* user_data);
-  static void connection_closed_callback(connection_error_e result,
-                                         void* user_data);
-
-  void registStateChangeListener(const std::string& domain_name);
-  void deregistStateChangeListener(const std::string& domain_name);
-
-  void makeSuccessCallback(const std::string& domain_name);
-  void makeErrorCallback(const std::string& domain_name, const char* info);
-  void makeErrorCallback(const std::string& domain_name,
-                         const std::string& info);
+  static void connection_state_changed_callback(connection_profile_state_e state, void* user_data);
+  static void connection_opened_callback(connection_error_e result, void* user_data);
+  static void connection_closed_callback(connection_error_e result, void* user_data);
+  static void connection_closed_callback(connection_error_e result, common::PlatformResult);
+
+  bool registerStateChangeListener(const std::string& domain_name);
+  bool deregisterStateChangeListener(const std::string& domain_name);
+
   common::ErrorCode GetNBSErrorCode(int error_code);
-  void makeDisconnectCallback(const std::string& domain_name);
-  void destroyProfileHandle();
-  RequestEventPtr getRequestEvent(NetworkBearerSelectionRequestEvent* event);
-  ReleaseEventPtr getReleaseEvent(NetworkBearerSelectionReleaseEvent* event);
+  void makeSuccessCallback();
+  void makeDisconnectCallback();
+
+  bool removeDomainRoute(const std::map<std::string, int>::iterator& iter);
+  bool createProfileHandler();
+  void destroyProfileHandler();
 
   NetworkBearerSelectionManager();
   ~NetworkBearerSelectionManager();
 
-  std::list<NetworkBearerSelectionListener*> m_listeners_;
+  std::list<NetworkBearerSelectionInstance*> m_listeners_;
 
   connection_h m_connection_handle_;
   connection_profile_h m_profile_handle_;
-  std::list<std::string> m_domain_names_;
-  std::vector<RequestEventPtr> m_request_events_;
-  std::vector<ReleaseEventPtr> m_release_events_;
-  ConnectionState m_connection_state_;
-  bool m_is_connection_open_;
+  std::string m_profile_name_;
+  std::map<std::string, int> m_domain_names_;
+  bool m_is_connection_opened_;
 
   std::mutex m_mutex_;
-  std::mutex m_request_mutex_;
-  std::mutex m_release_mutex_;
 };
 
 }  // namespace networkbearerselection