summaryrefslogtreecommitdiff
path: root/src/components/connection_handler/src/connection_handler_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/connection_handler/src/connection_handler_impl.cc')
-rw-r--r--src/components/connection_handler/src/connection_handler_impl.cc264
1 files changed, 249 insertions, 15 deletions
diff --git a/src/components/connection_handler/src/connection_handler_impl.cc b/src/components/connection_handler/src/connection_handler_impl.cc
index 62a1f46fba..7ea9efa1cc 100644
--- a/src/components/connection_handler/src/connection_handler_impl.cc
+++ b/src/components/connection_handler/src/connection_handler_impl.cc
@@ -38,6 +38,7 @@
#include "connection_handler/connection_handler_impl.h"
#include "transport_manager/info.h"
+#include "encryption/hashing.h"
#ifdef ENABLE_SECURITY
#include "security_manager/security_manager.h"
@@ -69,7 +70,9 @@ ConnectionHandlerImpl::ConnectionHandlerImpl(
, protocol_handler_(NULL)
, connection_list_lock_()
, connection_handler_observer_lock_()
- , connection_list_deleter_(&connection_list_) {}
+ , connection_list_deleter_(&connection_list_)
+ , start_service_context_map_lock_()
+ , start_service_context_map_() {}
ConnectionHandlerImpl::~ConnectionHandlerImpl() {
LOG4CXX_AUTO_TRACE(logger_);
@@ -82,6 +85,9 @@ void ConnectionHandlerImpl::Stop() {
RemoveConnection(itr->second->connection_handle());
itr = connection_list_.begin();
}
+
+ sync_primitives::AutoLock auto_lock(start_service_context_map_lock_);
+ start_service_context_map_.clear();
}
void ConnectionHandlerImpl::set_connection_handler_observer(
@@ -131,15 +137,21 @@ void ConnectionHandlerImpl::OnDeviceFound(
void ConnectionHandlerImpl::OnDeviceAdded(
const transport_manager::DeviceInfo& device_info) {
LOG4CXX_AUTO_TRACE(logger_);
- device_list_.insert(
- DeviceMap::value_type(device_info.device_handle(),
- Device(device_info.device_handle(),
- device_info.name(),
- device_info.mac_address(),
- device_info.connection_type())));
- sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
- if (connection_handler_observer_) {
- connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ auto handle = device_info.device_handle();
+
+ Device device(handle,
+ device_info.name(),
+ device_info.mac_address(),
+ device_info.connection_type());
+
+ auto result = device_list_.insert(std::make_pair(handle, device));
+
+ if (!result.second) {
+ LOG4CXX_ERROR(logger_,
+ "Device with handle " << handle
+ << " is known already. "
+ "Information won't be updated.");
+ return;
}
}
@@ -169,10 +181,54 @@ void ConnectionHandlerImpl::OnDeviceRemoved(
RemoveConnection(*it);
}
- device_list_.erase(device_info.device_handle());
sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
if (connection_handler_observer_) {
connection_handler_observer_->RemoveDevice(device_info.device_handle());
+ connection_handler_observer_->OnDeviceListUpdated(device_list_);
+ }
+ device_list_.erase(device_info.device_handle());
+}
+
+void ConnectionHandlerImpl::OnDeviceSwitchingFinish(
+ const transport_manager::DeviceUID& device_uid) {
+ sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnDeviceSwitchingFinish(
+ encryption::MakeHash(device_uid));
+ }
+}
+
+namespace {
+struct DeviceFinder {
+ explicit DeviceFinder(const std::string& device_uid)
+ : device_uid_(device_uid) {}
+ bool operator()(const DeviceMap::value_type& device) {
+ return device_uid_ == device.second.mac_address();
+ }
+
+ private:
+ const std::string& device_uid_;
+};
+} // namespace
+
+void ConnectionHandlerImpl::OnDeviceSwitchingStart(
+ const std::string& device_uid_from, const std::string& device_uid_to) {
+ auto device_from =
+ std::find_if(device_list_.begin(),
+ device_list_.end(),
+ DeviceFinder(encryption::MakeHash(device_uid_from)));
+
+ auto device_to =
+ std::find_if(device_list_.begin(),
+ device_list_.end(),
+ DeviceFinder(encryption::MakeHash(device_uid_to)));
+
+ DCHECK_OR_RETURN_VOID(device_list_.end() != device_from);
+ DCHECK_OR_RETURN_VOID(device_list_.end() != device_to);
+ sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
+ if (connection_handler_observer_) {
+ connection_handler_observer_->OnDeviceSwitchingStart(device_from->second,
+ device_to->second);
}
}
@@ -289,6 +345,7 @@ uint32_t ConnectionHandlerImpl::OnSessionStartedCallback(
if (hash_id) {
*hash_id = protocol_handler::HASH_ID_WRONG;
}
+
#ifdef ENABLE_SECURITY
if (!AllowProtection(get_settings(), service_type, is_protected)) {
return 0;
@@ -347,6 +404,139 @@ uint32_t ConnectionHandlerImpl::OnSessionStartedCallback(
return new_session_id;
}
+void ConnectionHandlerImpl::OnSessionStartedCallback(
+ const transport_manager::ConnectionUID connection_handle,
+ const uint8_t session_id,
+ const protocol_handler::ServiceType& service_type,
+ const bool is_protected,
+ const BsonObject* params) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ std::vector<std::string> rejected_params;
+ protocol_handler::SessionContext context(connection_handle,
+ session_id,
+ 0,
+ service_type,
+ protocol_handler::HASH_ID_WRONG,
+ is_protected);
+
+#ifdef ENABLE_SECURITY
+ if (!AllowProtection(get_settings(), service_type, is_protected)) {
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ return;
+ }
+#endif // ENABLE_SECURITY
+ sync_primitives::AutoReadLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ return;
+ }
+
+ Connection* connection = it->second;
+ context.is_new_service_ =
+ !connection->SessionServiceExists(session_id, service_type);
+
+ if ((0 == session_id) && (protocol_handler::kRpc == service_type)) {
+ context.new_session_id_ = connection->AddNewSession();
+ if (0 == context.new_session_id_) {
+ LOG4CXX_ERROR(logger_, "Couldn't start new session!");
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ return;
+ }
+ context.hash_id_ = KeyFromPair(connection_handle, context.new_session_id_);
+ } else { // Could be create new service or protected exists one
+ if (!connection->AddNewService(session_id, service_type, is_protected)) {
+ LOG4CXX_ERROR(logger_,
+ "Couldn't establish "
+#ifdef ENABLE_SECURITY
+ << (is_protected ? "protected" : "non-protected")
+#endif // ENABLE_SECURITY
+ << " service " << static_cast<int>(service_type)
+ << " for session " << static_cast<int>(session_id));
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ return;
+ }
+ context.new_session_id_ = session_id;
+ context.hash_id_ = protocol_handler::HASH_ID_NOT_SUPPORTED;
+ }
+ sync_primitives::AutoReadLock read_lock(connection_handler_observer_lock_);
+ if (connection_handler_observer_) {
+ const uint32_t session_key =
+ KeyFromPair(connection_handle, context.new_session_id_);
+
+ uint32_t app_id = 0;
+ GetDataOnSessionKey(
+ session_key, &app_id, NULL, static_cast<DeviceHandle*>(NULL));
+ if (app_id > 0) {
+ context.is_ptu_required_ =
+ !connection_handler_observer_->CheckAppIsNavi(app_id);
+ }
+
+ {
+ sync_primitives::AutoLock auto_lock(start_service_context_map_lock_);
+ start_service_context_map_[session_key] = context;
+ }
+
+ connection_handler_observer_->OnServiceStartedCallback(
+ connection->connection_device_handle(),
+ session_key,
+ service_type,
+ params);
+ } else {
+ if (protocol_handler_) {
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ }
+ }
+}
+
+void ConnectionHandlerImpl::NotifyServiceStartedResult(
+ uint32_t session_key,
+ bool result,
+ std::vector<std::string>& rejected_params) {
+ LOG4CXX_AUTO_TRACE(logger_);
+
+ protocol_handler::SessionContext context;
+ {
+ sync_primitives::AutoLock auto_lock(start_service_context_map_lock_);
+ auto it = start_service_context_map_.find(session_key);
+ if (it == start_service_context_map_.end()) {
+ LOG4CXX_ERROR(logger_, "context for start service not found!");
+ return;
+ }
+ context = it->second;
+ start_service_context_map_.erase(it);
+ }
+
+ Connection* connection = NULL;
+ {
+ sync_primitives::AutoReadLock lock(connection_list_lock_);
+ ConnectionList::iterator it = connection_list_.find(context.connection_id_);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "connection not found");
+ return;
+ }
+ connection = it->second;
+ }
+
+ if (!result) {
+ LOG4CXX_WARN(logger_,
+ "Service starting forbidden by connection_handler_observer");
+ if (protocol_handler::kRpc == context.service_type_) {
+ connection->RemoveSession(context.new_session_id_);
+ } else {
+ connection->RemoveService(context.initial_session_id_,
+ context.service_type_);
+ }
+ context.new_session_id_ = 0;
+ }
+
+ if (protocol_handler_ != NULL) {
+ protocol_handler_->NotifySessionStarted(context, rejected_params);
+ }
+}
+
void ConnectionHandlerImpl::OnApplicationFloodCallBack(
const uint32_t& connection_key) {
LOG4CXX_AUTO_TRACE(logger_);
@@ -382,12 +572,23 @@ uint32_t ConnectionHandlerImpl::OnSessionEndedCallback(
const uint8_t session_id,
const uint32_t& hashCode,
const protocol_handler::ServiceType& service_type) {
+ uint32_t hashValue = hashCode;
+ return OnSessionEndedCallback(
+ connection_handle, session_id, &hashValue, service_type);
+}
+
+uint32_t ConnectionHandlerImpl::OnSessionEndedCallback(
+ const transport_manager::ConnectionUID connection_handle,
+ const uint8_t session_id,
+ uint32_t* hashCode,
+ const protocol_handler::ServiceType& service_type) {
LOG4CXX_AUTO_TRACE(logger_);
connection_list_lock_.AcquireForReading();
ConnectionList::iterator it = connection_list_.find(connection_handle);
if (connection_list_.end() == it) {
LOG4CXX_WARN(logger_, "Unknown connection!");
+ connection_list_lock_.Release();
return 0;
}
std::pair<int32_t, Connection*> connection_item = *it;
@@ -401,12 +602,13 @@ uint32_t ConnectionHandlerImpl::OnSessionEndedCallback(
"Session " << static_cast<uint32_t>(session_id)
<< " to be removed");
// old version of protocol doesn't support hash
- if (protocol_handler::HASH_ID_NOT_SUPPORTED != hashCode) {
- if (protocol_handler::HASH_ID_WRONG == hashCode ||
- session_key != hashCode) {
+ if (protocol_handler::HASH_ID_NOT_SUPPORTED != *hashCode) {
+ if (protocol_handler::HASH_ID_WRONG == *hashCode ||
+ session_key != *hashCode) {
LOG4CXX_WARN(logger_,
"Wrong hash_id for session "
<< static_cast<uint32_t>(session_id));
+ *hashCode = protocol_handler::HASH_ID_WRONG;
return 0;
}
}
@@ -470,7 +672,7 @@ int32_t ConnectionHandlerImpl::GetDataOnSessionKey(
uint32_t key,
uint32_t* app_id,
std::list<int32_t>* sessions_list,
- uint32_t* device_id) const {
+ connection_handler::DeviceHandle* device_id) const {
LOG4CXX_AUTO_TRACE(logger_);
const int32_t error_result = -1;
@@ -514,6 +716,18 @@ int32_t ConnectionHandlerImpl::GetDataOnSessionKey(
return 0;
}
+int32_t ConnectionHandlerImpl::GetDataOnSessionKey(
+ uint32_t key,
+ uint32_t* app_id,
+ std::list<int32_t>* sessions_list,
+ uint32_t* device_id) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ DeviceHandle handle;
+ int32_t result = GetDataOnSessionKey(key, app_id, sessions_list, &handle);
+ *device_id = static_cast<uint32_t>(handle);
+ return result;
+}
+
const ConnectionHandlerSettings& ConnectionHandlerImpl::get_settings() const {
return settings_;
}
@@ -664,10 +878,29 @@ void ConnectionHandlerImpl::SetProtectionFlag(
connection.SetProtectionFlag(session_id, service_type);
}
+bool ConnectionHandlerImpl::SessionServiceExists(
+ const uint32_t connection_key,
+ const protocol_handler::ServiceType& service_type) const {
+ LOG4CXX_AUTO_TRACE(logger_);
+ transport_manager::ConnectionUID connection_handle = 0;
+ uint8_t session_id = 0;
+ PairFromKey(connection_key, &connection_handle, &session_id);
+
+ sync_primitives::AutoReadLock lock(connection_list_lock_);
+ ConnectionList::const_iterator it = connection_list_.find(connection_handle);
+ if (connection_list_.end() == it) {
+ LOG4CXX_ERROR(logger_, "Unknown connection!");
+ return false;
+ }
+ const Connection& connection = *it->second;
+ return connection.SessionServiceExists(session_id, service_type);
+}
+
security_manager::SSLContext::HandshakeContext
ConnectionHandlerImpl::GetHandshakeContext(uint32_t key) const {
return connection_handler_observer_->GetHandshakeContext(key);
}
+
#endif // ENABLE_SECURITY
void ConnectionHandlerImpl::StartDevicesDiscovery() {
@@ -944,6 +1177,7 @@ void ConnectionHandlerImpl::OnConnectionEnded(
ConnectionList::iterator itr = connection_list_.find(connection_id);
if (connection_list_.end() == itr) {
LOG4CXX_ERROR(logger_, "Connection not found!");
+ connection_list_lock_.Release();
return;
}
std::auto_ptr<Connection> connection(itr->second);