#include <functional>
+#include "networkbearerselection_manager.h"
#include "common/picojson.h"
#include "common/logger.h"
#include "common/platform_exception.h"
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;
}
NetworkBearerSelectionInstance::~NetworkBearerSelectionInstance() {
- LoggerD("Enter");
+ LoggerD("Entered");
NetworkBearerSelectionManager::GetInstance()->RemoveListener(this);
}
}
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);
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);
}
#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;
}
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 {
}
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, ¤t_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, ¤tProfileName_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